Introduction
This notebook contains analyses from the MEDAL study, assessing
memory bias in remitted and depressed individuals. The pre-registration
for the main analyses, as well as a preprint version of the accompanying
article can be found here as well.
The main aim of the current work was to examine how three groups
(control, remitted, depressed) differ in terms of emotional memory
dynamics in a real-life setting.
#Load packages
Warning message:
In Sys.timezone() : unable to identify current timezone 'C':
please set environment variable 'TZ'
#renv::activate()
library(dplyr)
Attaching package: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(janitor)
Attaching package: ‘janitor’
The following objects are masked from ‘package:stats’:
chisq.test, fisher.test
library(readxl)
library(data.table)
data.table 1.14.8 using 4 threads (see ?getDTthreads). Latest news: r-datatable.com
Attaching package: ‘data.table’
The following objects are masked from ‘package:dplyr’:
between, first, last
library(ggplot2)
Learn more about the underlying theory at https://ggplot2-book.org/
library(psych)
Attaching package: ‘psych’
The following objects are masked from ‘package:ggplot2’:
%+%, alpha
library(devtools)
Loading required package: usethis
library(pastecs)
Attaching package: ‘pastecs’
The following objects are masked from ‘package:data.table’:
first, last
The following objects are masked from ‘package:dplyr’:
first, last
library(cli)
library(lmerTest) #linear mixed models
Loading required package: lme4
Loading required package: Matrix
Attaching package: ‘lmerTest’
The following object is masked from ‘package:lme4’:
lmer
The following object is masked from ‘package:stats’:
step
library(performance) #fits of residuals
library(DescTools)
Registered S3 method overwritten by 'DescTools':
method from
print.palette wesanderson
Attaching package: ‘DescTools’
The following objects are masked from ‘package:psych’:
AUC, ICC, SD
The following object is masked from ‘package:data.table’:
%like%
library(tidyr) # Separate trigger column
Attaching package: ‘tidyr’
The following objects are masked from ‘package:Matrix’:
expand, pack, unpack
The following object is masked from ‘package:pastecs’:
extract
library(sjPlot) # for nice tables and interaction plots
library(knitr) # to print the tables within notebook
library(foreach) #run parallel loops
Attaching package: ‘foreach’
The following object is masked from ‘package:DescTools’:
%:%
library(parallel)
library(doParallel) #run parallel loops
Loading required package: iterators
library(ggpubr) # emmeans
library(mediation) #mediation analysis
Loading required package: MASS
Attaching package: ‘MASS’
The following object is masked from ‘package:dplyr’:
select
Loading required package: mvtnorm
Loading required package: sandwich
mediation: Causal Mediation Analysis
Version: 4.5.0
Attaching package: ‘mediation’
The following object is masked from ‘package:psych’:
mediate
library(plotly) #for interactive plots
Attaching package: ‘plotly’
The following object is masked from ‘package:MASS’:
select
The following object is masked from ‘package:ggplot2’:
last_plot
The following object is masked from ‘package:stats’:
filter
The following object is masked from ‘package:graphics’:
layout
library(jtools) #for theme_apa
Attaching package: ‘jtools’
The following object is masked from ‘package:mvtnorm’:
standardize
The following object is masked from ‘package:DescTools’:
%nin%
library(JSmediation) #moderated mediation
library(wesanderson)
source("functions.R")
Data
Here we load in our data and preprocess it in steps. We first need to
separate the different surveys that were delivered to bring them into
the same sampling times, merge in some descriptives we need as
covariates, and estimate subject-centered and lagged variables for our
models later.
- Load and clean data
# Load the data
MEDAL_ESM_compleet <- read_excel("data/MEDAL_ESM_compleet.xlsx")
# Move variables around and clean names
MEDAL_ESM_compleet= MEDAL_ESM_compleet %>%
rename(id='Movisens-ID') %>%
clean_names() %>%
rename(subjectcode = 'deelnemersnr') %>%
relocate('subjectcode', .after = 'id')
df_medal_try = MEDAL_ESM_compleet
- Split different EMA surveys we have
# Sleep EMA Qs
df_medal_sleep = df_medal_try %>%
filter(form=='Slaap') %>%
dplyr::select(c(1, 2, 4, 5, 7, 9, 14))
# Recent EMA Qs
df_medal_recent = df_medal_try %>%
filter(form=='Recent') %>%
dplyr::select(c(1, 2, 4, 5, 7, 9, contains('rec')))
# Remote EMA Qs
df_medal_remote = df_medal_try %>%
filter(form=='Remote') %>%
dplyr::select(c(1, 2, 4, 5, 7, 9, contains('rem')))
# Mastery EMA Qs
df_medal_mastery = df_medal_try %>%
filter(form=='Mastery') %>%
dplyr::select(c(1, 2, 4, 5, 7, 9, contains('master')))
# Standard Qs
df_medal_standard = df_medal_try %>%
filter(form=='Standaard') %>%
dplyr::select(c(1, 2, 4, 5, 7, 9, (-contains('mastery') & -contains('rem') & -contains('rec')))) %>%
dplyr::select(-c(7,13,14))
# merge sleep and standard
df_medal_merged = merge(df_medal_sleep, df_medal_standard, by=c('id', 'trigger_counter', 'subjectcode'), suffixes = c("_sleep", ""), all=T )
# merge to recent, remote and mastery
df_medal_merged= merge(df_medal_merged, df_medal_recent, by=c('id', 'trigger_counter', 'subjectcode' ), suffixes = c('', '_recent'), all = T )
df_medal_merged = merge(df_medal_merged, df_medal_remote, by=c('id', 'trigger_counter', 'subjectcode' ), suffixes = c('', '_remote'), all = T )
df_medal_merged = merge(df_medal_merged, df_medal_mastery, by=c('id', 'trigger_counter', 'subjectcode' ), suffixes = c('', '_mastery'), all = T )
# Fix start dates and times
df_medal_merged$form_start_date <- as.character(df_medal_merged$form_start_date)
df_medal_merged$form_start_date <- as.ITime(df_medal_merged$form_start_date)
df_medal_merged = df_medal_merged %>%
dplyr::mutate(form_start_date = ifelse(is.na(form_start_date), form_start_date_sleep, form_start_date))
- Add variables on Education, Gender, and Age
# Load in previous data for demographics (also contains EMA)
load("data/IPAQ_Maeve_Workspace.RData")
df_MEDAL <- df_MEDAL[-c(192), ]
# Select relevant demo info
df_MEDAL = df_MEDAL %>%
dplyr::select(1, 3, 5:7) %>%
rename('subjectcode' = 'subject', 'education' = 'Education3groups', 'n_episodes'='NumberEpisodes' )
# merge demo to full EMA
df_medal_merged = merge(df_medal_merged, df_MEDAL, by = c('subjectcode'), all = T ) %>%
clean_names()
df_medal_merged$education = as.factor(df_medal_merged$education)
df_medal_merged$gender = as.factor(df_medal_merged$gender)
df_medal_merged = df_medal_merged %>%
relocate(c('id', 'gender', 'age', 'education'), .after = 'subjectcode') %>%
relocate ('age', .after = 'gender') %>%
relocate ('education', .after = 'age') %>%
relocate ('id', .before = 'subjectcode')
- Categorize the subjectcode into the three conditions (Depressed,
Remitted, Control (Never-depressed))
df_medal_merged$condition = case_when(df_medal_merged$subjectcode >= 700 & df_medal_merged$subjectcode < 800 ~ "remitted", df_medal_merged$subjectcode >= 800 & df_medal_merged$subjectcode < 900 ~ "depressed", df_medal_merged$subjectcode >= 900 ~ "control")
df_medal_merged = df_medal_merged %>% relocate ('condition', .after = 'subjectcode' )
df_medal_merged$condition <- as.factor(df_medal_merged$condition)
- Calculate reaction time
df_medal_merged$rt_sleep = lubridate::as.difftime( df_medal_merged$form_finish_date_sleep - df_medal_merged$form_start_date_sleep)
- Separate time from when trigger was sent
df_medal_merged = df_medal_merged %>%
tidyr::separate(trigger, c('Random', 'Time', 'Trigger_Time_1', 'Trigger_Time_2')) %>%
dplyr::mutate(trigger_time = paste(Trigger_Time_1, Trigger_Time_2, sep=':')) %>%#separate time from previous trigger
dplyr::mutate(trigger = paste(Random, Time, trigger_time, sep=' ')) #bring back 'trigger' column
#Turn numbers into time format
df_medal_merged$trigger_time <- as.ITime(df_medal_merged$trigger_time)
- Find the trigger number per day
#df_medal_merged$trigger_counter[is.na(df_medal_merged$trigger_time)] <- 1
df_medal_merged$trigger_number[is.na(df_medal_merged$trigger_time)] <- 1
df_medal_merged$trigger_number[df_medal_merged$trigger_time >= (as.ITime("10:00:00"))& df_medal_merged$trigger_time < (as.ITime("12:00:00"))] <- 2
df_medal_merged$trigger_number[df_medal_merged$trigger_time >= (as.ITime("12:00:00"))& df_medal_merged$trigger_time < (as.ITime("14:00:00"))] <- 3
df_medal_merged$trigger_number[df_medal_merged$trigger_time >= (as.ITime("14:00:00"))& df_medal_merged$trigger_time < (as.ITime("16:00:00"))] <- 4
df_medal_merged$trigger_number[df_medal_merged$trigger_time >= (as.ITime("16:00:00"))& df_medal_merged$trigger_time < (as.ITime("18:00:00"))] <- 5
df_medal_merged$trigger_number[df_medal_merged$trigger_time >= (as.ITime("18:00:00"))& df_medal_merged$trigger_time < (as.ITime("20:00:00"))] <- 6
df_medal_merged$trigger_number[df_medal_merged$trigger_time >= (as.ITime("20:00:00"))& df_medal_merged$trigger_time < (as.ITime("23:00:01"))] <- 7
# df
df_medal_merged = df_medal_merged %>%
relocate ('trigger_number', .after = 'trigger_counter')%>% relocate('trigger_time', .before ='form_start_date') %>%
relocate('trigger', .before ='trigger_time')
- Final cleaning of the dataset
#Create dataset where double morning list is removed
df_medal_merged = df_medal_merged %>%
dplyr::mutate(trigger_counter=ifelse(trigger_number==1 & lag(trigger_number)==1, lag(trigger_counter), trigger_counter)) %>%
dplyr::mutate(trigger_counter=ifelse(trigger_number==1 & lag(trigger_number)==1, lag(trigger_counter), trigger_counter)) %>%
dplyr::mutate(trigger_counter=ifelse(trigger_number==1 & lag(trigger_number)==1, lag(trigger_counter), trigger_counter)) %>%
dplyr::mutate(trigger_counter=ifelse(trigger_number==1 & lag(trigger_number)==1, lag(trigger_counter), trigger_counter)) %>%
dplyr::mutate(trigger_counter=ifelse(trigger_number==1 & lag(trigger_number)==1, lag(trigger_counter), trigger_counter))
# now we have the clean dataframe, remove duplicated coloumns
df_medal_clean = df_medal_merged %>%
dplyr::group_by(subjectcode) %>%
distinct(trigger_counter, .keep_all = TRUE) %>%
dplyr::select (1:12, 17:60) %>%
dplyr::mutate(original_order = row_number()) %>%
relocate('original_order', .before = 'id')
#Set the order of the factor to control, remission, depression (for visual purposes)
df_medal_clean$condition <- factor(df_medal_clean$condition, levels=c('control', 'remitted', 'depressed' ), labels=c('control', 'remitted', 'depressed'))
# Create dummy variable
df_medal_clean = df_medal_clean %>%
mutate(condition_dummy = case_when(condition == 'depressed'~ 3, condition == 'remitted'~ 2, condition == 'control' ~ 1))
df_medal_clean$condition_dummy = as.factor(df_medal_clean$condition_dummy)
#set weekday
df_medal_clean$form_finish_date <- as.character(df_medal_clean$form_finish_date)
df_medal_clean$form_finish_date <- strptime(df_medal_clean$form_finish_date, format = '%Y-%m-%d %H:%M:%S')
df_medal_clean$finish_date <- as.Date(df_medal_clean$form_finish_date)
df_medal_clean$weekday <- as.integer(format(df_medal_clean$finish_date, '%w'))
df_medal_clean = df_medal_clean %>% relocate('weekday', .after = 'trigger_number')
#solve duplicate issue
df_medal_duplicate = df_medal_clean %>% dplyr::group_by(subjectcode, weekday) %>% filter(duplicated(trigger_number))
#since row 10 for subject 712 is a duplicate morning list
df_medal_clean <- subset(df_medal_clean, !(subjectcode == 712 & original_order == 10))
df_medal_clean = df_medal_clean %>% dplyr::group_by(subjectcode, weekday) %>%
mutate(temp = lead(trigger_number),
trigger_number = case_when(trigger_number == temp ~ (temp -1), TRUE ~ trigger_number)) %>%
select(-temp)
#Take the rows out that have 'NA'for the weekday since form wasn't finished and there is no data for PA, NA, or Memory
df_medal_clean = df_medal_clean %>% filter(!is.na(weekday))
df_medal_clean$original_order <- 1:nrow(df_medal_clean)
# Create expanded df with all potential datapoints
df_medal_day = df_medal_clean %>%
dplyr::select('subjectcode', 'weekday', 'original_order') %>%
dplyr::mutate(weekday = as.numeric(weekday)) %>%
dplyr::group_by(subjectcode) %>%
dplyr:: distinct(weekday, .keep_all =T) %>%
dplyr::ungroup()
df_medal_day = df_medal_day %>%
slice(rep(1:n(), each = 7)) %>%
dplyr::mutate(trigger_number = rep(1:7, length.out=n())) %>%
dplyr::rename(order = original_order)
#merge with main dataframe
df_medal_clean = merge(df_medal_day, df_medal_clean, by=c('subjectcode', 'trigger_number', 'weekday'), all= T)
df_medal_clean = df_medal_clean %>% mutate(order = as.numeric(order))
df_medal_clean = arrange(df_medal_clean, order)
- Centre, scale, and average Variables
used_vars = c("neg_mood", "rec_mem_neg_mood", "rem_mem_neg_mood", "pos_mood", "rec_mem_pos_mood", "rem_mem_pos_mood")
#Centering & scaling
df_medal_clean = df_medal_clean %>%
dplyr::group_by(subjectcode) %>%
# Center and scale
dplyr::mutate( across(used_vars, ~ (.x/10), .names = "{.col}" ),
across(used_vars, ~ mean(.x, na.rm=T), .names = "{.col}_m" ),
across(used_vars, ~ (.x - mean(.x, na.rm=T)), .names = "{.col}_c" ),
across(paste0(used_vars, "_c"), ~ DescTools::Winsorize(.x, na.rm = T), .names = "{.col}")) %>%
ungroup() %>%
# Rescale to positive
mutate(across(c(paste0(used_vars,"_c")), ~ abs(min(.x, na.rm = T)) + 1 + .x, .names = "{.col}s"))
- Lag variables
# Remote
df_medal_clean = df_medal_clean %>%
dplyr::group_by(subjectcode) %>%
mutate(rem_mem_pos_mood_lag = lead(rem_mem_pos_mood, n=7, order_by=subjectcode),
rem_mem_neg_mood_lag = lead(rem_mem_neg_mood, n=7, order_by=subjectcode),
pos_mood_lag_rem = lead(pos_mood, n=7, order_by=subjectcode),
neg_mood_lag_rem = lead(neg_mood, n=7, order_by=subjectcode),
rem_mem_pos_mood_cs_lag = lead(rem_mem_pos_mood_cs, n=7, order_by=subjectcode),
rem_mem_neg_mood_cs_lag = lead(rem_mem_neg_mood_cs, n=7, order_by=subjectcode),
pos_mood_cs_lag_rem = lead(pos_mood_cs, n=7, order_by=subjectcode),
neg_mood_cs_lag_rem = lead(neg_mood_cs, n=7, order_by=subjectcode),
rem_mem_pos_mood_c_lag = lead(rem_mem_pos_mood_c, n=7, order_by=subjectcode),
rem_mem_neg_mood_c_lag = lead(rem_mem_neg_mood_c, n=7, order_by=subjectcode),
pos_mood_c_lag_rem = lead(pos_mood_c, n=7, order_by=subjectcode),
neg_mood_c_lag_rem = lead(neg_mood_c, n=7, order_by=subjectcode)) %>%
filter(!is.na(original_order)) # filter out the NA rows for the lagging of recent memory
# Recent
df_medal_clean = df_medal_clean %>%
dplyr::group_by(subjectcode) %>%
mutate(rec_mem_pos_mood_lag = lead(rec_mem_pos_mood, n=1, order_by=subjectcode),
rec_mem_neg_mood_lag = lead(rec_mem_neg_mood, n=1, order_by=subjectcode),
pos_mood_lag_rec = lead(pos_mood, n=1, order_by=subjectcode),
neg_mood_lag_rec = lead(neg_mood, n=1, order_by=subjectcode),
rec_mem_pos_mood_cs_lag = lead(rec_mem_pos_mood_cs, n=1, order_by=subjectcode),
rec_mem_neg_mood_cs_lag = lead(rec_mem_neg_mood_cs, n=1, order_by=subjectcode),
pos_mood_cs_lag_rec = lead(pos_mood_cs, n=1, order_by=subjectcode),
neg_mood_cs_lag_rec = lead(neg_mood_cs, n=1, order_by=subjectcode),
rec_mem_pos_mood_c_lag = lead(rec_mem_pos_mood_c, n=1, order_by=subjectcode),
rec_mem_neg_mood_c_lag = lead(rec_mem_neg_mood_c, n=1, order_by=subjectcode),
pos_mood_c_lag_rec = lead(pos_mood_c, n=1, order_by=subjectcode),
neg_mood_c_lag_rec = lead(neg_mood_c, n=1, order_by=subjectcode)) %>%
ungroup()
Descriptives
We first plot some general population descriptives, followed by some
descriptives of the scales we use in the EMA weeks and compliance
rates.
Population Descriptives
#Create Descriptives Tables
summary_table = df_medal_clean %>% distinct(subjectcode, .keep_all = TRUE) %>% group_by(condition) %>% summarise(
'N' = n(),
'Age \n M +/- SD' = paste0(round(mean(age, na.rm =T), 1), ' +/- ' , round(sd(age, na.rm =T), 1)),
#'NA Age' = sum(is.na(age)),
'% Education Low' = mean(education == 0, na.rm = T)*100,
'% Education Middle' = mean(education == 1, na.rm = T)*100,
'% Education High' = mean(education == 2, na.rm = T)*100,
#'NA Education' = sum(is.na(education)),
'% Female' = mean(gender ==1, na.rm = T)*100,
#'NA Gender' = sum(is.na(gender))
)
#Compliance rates
df_medal_compliance_individual = df_medal_clean %>% group_by(condition, subjectcode) %>% summarise('ComplianceRate' = sum(!is.na(trigger_number))/42*100)
`summarise()` has grouped output by 'condition'. You can override using the `.groups` argument.
length(which(df_medal_compliance_individual$ComplianceRate <70))
[1] 8
df_medal_compliance = df_medal_clean %>% group_by(condition) %>% summarise('% Mean Compliance' = sum(!is.na(trigger_number))/(n_distinct(subjectcode) *42)*100)
# Create a table
summary_table = summary_table %>% left_join(df_medal_compliance, by = 'condition')
rempsyc::nice_table(summary_table)
condition | N | Age M +/- SD | % Education Low | % Education Middle | % Education High | % Female | % Mean Compliance |
|---|
control | 55 | 51.7 +/- 10.9 | 0.00 | 22.64 | 77.36 | 78.18 | 92.42 |
remitted | 90 | 52.5 +/- 11.1 | 3.49 | 16.28 | 80.23 | 78.41 | 91.88 |
depressed | 46 | 48.7 +/- 11.2 | 4.35 | 30.43 | 65.22 | 71.74 | 92.65 |
#create dataset with only unique subjectcode
df_medal_distinct = df_medal_clean %>% distinct(subjectcode, .keep_all = TRUE)%>% select('subjectcode', 'condition', 'age', 'education', 'gender')
#Test for differences between groups
#Age
df_medal_distinct %>% lm(age ~ condition, data=.) %>% summary()
Call:
lm(formula = age ~ condition, data = .)
Residuals:
Min 1Q Median 3Q Max
-26.717 -6.511 2.489 7.489 18.283
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 51.6727 1.4876 34.736 <2e-16 ***
conditionremitted 0.8386 1.8963 0.442 0.659
conditiondepressed -2.9553 2.2042 -1.341 0.182
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 11.03 on 186 degrees of freedom
(2 observations deleted due to missingness)
Multiple R-squared: 0.0192, Adjusted R-squared: 0.008657
F-statistic: 1.821 on 2 and 186 DF, p-value: 0.1648
#education
chisq.test(df_medal_distinct$education, df_medal_distinct$condition)
Warning: Chi-squared approximation may be incorrect
Pearson's Chi-squared test
data: df_medal_distinct$education and df_medal_distinct$condition
X-squared = 5.8234, df = 4, p-value = 0.2127
#gender
chisq.test(df_medal_distinct$gender, df_medal_distinct$condition)
Pearson's Chi-squared test
data: df_medal_distinct$gender and df_medal_distinct$condition
X-squared = 0.84533, df = 2, p-value = 0.6553
#Create a Graph
#age
boxplot_age <- ggplot(df_medal_distinct, aes(x=condition, y=age, fill=condition)) +
geom_boxplot() +
labs(x = 'Condition', y = 'Age', tag = 'C' ) +
ggtitle('Age per Condition') +
scale_fill_manual(values = wesanderson::wes_palette(n=3, name='GrandBudapest2' )) +
theme_apa()
ggplotly(boxplot_age)
Warning: Removed 2 rows containing non-finite values (`stat_boxplot()`).
#education
plot_educ <- ggplot(df_medal_distinct, aes(x=condition, fill = education)) +
geom_bar(position = 'dodge') +
labs(x='Condition', y= 'Proportion', tag = 'A' ) +
ggtitle('Education Level per Condition') +
scale_fill_manual(values = wesanderson::wes_palette(n=3, name='GrandBudapest2' ), labels = c('Low' , 'Middle' , 'High'), name = 'Education') +
theme_apa()
ggplotly(plot_educ)
#Gender
plot_gender <- ggplot(df_medal_distinct, aes(x=condition, fill = gender)) +
geom_bar(position = 'dodge') +
labs(x = 'Condition', y = 'Proportion', tag = 'B' ) +
ggtitle('Gender per Condition') +
scale_fill_manual(values = wesanderson::wes_palette(n=3, name='GrandBudapest2' ), labels = c('Male', 'Female'), 'Gender') +
theme_apa()
ggplotly(plot_gender)
plot_gender_2 <- ggstatsplot::ggbarstats(data = df_medal_distinct, x = gender, y = condition) +
labs(x = 'Condition', y = 'Proportion', tag = 'B' ) +
ggtitle('Gender per Condition') +
scale_fill_manual(values = wesanderson::wes_palette(n=3, name='GrandBudapest2' ), labels = c('Male', 'Female'), 'Gender') +
theme_apa()
Scale for fill is already present.
Adding another scale for fill, which will replace the existing scale.
ggplotly(plot_gender_2)
Warning: geom_GeomLabel() has yet to be implemented in plotly.
If you'd like to see this geom implemented,
Please open an issue with your example code at
https://github.com/ropensci/plotly/issues
ggpubr::ggarrange(plot_educ, plot_gender, boxplot_age, nrow=2, ncol=2)
Warning: Removed 2 rows containing non-finite values (`stat_boxplot()`).

NA
Positive Mood
describe.by(df_medal_clean$pos_mood, group=df_medal_clean$condition) %>% rbindlist() %>% mutate(vars=c("cont", "rem", "dep"))
Warning: describe.by is deprecated. Please use the describeBy function
Distribution
ggplot(data= df_medal_clean, aes(x=pos_mood)) + geom_histogram()+facet_grid(cols=vars(condition))

Centred Distribution
ggplot(data= df_medal_clean, aes(x=pos_mood_c)) + geom_histogram()+facet_grid(cols=vars(condition))

Positive Recent Memory
describe.by(df_medal_clean$rec_mem_pos_mood, group=df_medal_clean$condition) %>% rbindlist() %>% mutate(vars=c("cont", "rem", "dep"))
Warning: describe.by is deprecated. Please use the describeBy function
Distribution
ggplot(data= df_medal_clean, aes(x=rec_mem_pos_mood)) + geom_histogram()+facet_grid(cols=vars(condition))

Centred Distribution
ggplot(data= df_medal_clean, aes(x=rec_mem_pos_mood_c)) + geom_histogram()+facet_grid(cols=vars(condition))

Positive Remote Memory
describe.by(df_medal_clean$rem_mem_pos_mood, group=df_medal_clean$condition) %>% rbindlist() %>% mutate(vars=c("cont", "rem", "dep"))
Warning: describe.by is deprecated. Please use the describeBy function
Distribution
ggplot(data= df_medal_clean, aes(x=rem_mem_pos_mood)) + geom_histogram()+facet_grid(cols=vars(condition))

Centred Distribution
ggplot(data= df_medal_clean, aes(x=rem_mem_pos_mood_c)) + geom_histogram()+facet_grid(cols=vars(condition))

Negative Mood
describe.by(df_medal_clean$neg_mood, group=df_medal_clean$condition)%>% rbindlist() %>% mutate(vars=c("cont", "rem", "dep"))
Warning: describe.by is deprecated. Please use the describeBy function
Distribution
ggplot(data= df_medal_clean, aes(x=neg_mood)) + geom_histogram()+facet_grid(cols=vars(condition))

Centred Distribution
ggplot(data= df_medal_clean, aes(x=neg_mood_c)) + geom_histogram()+facet_grid(cols=vars(condition))

ggplot(data= df_medal_clean, aes(x=neg_mood_cs)) + geom_histogram()+facet_grid(cols=vars(condition))

Negative Recent Memory
describe.by(df_medal_clean$rec_mem_neg_mood, group=df_medal_clean$condition) %>% rbindlist() %>% mutate(vars=c("cont", "rem", "dep"))
Warning: describe.by is deprecated. Please use the describeBy function
Distribution
ggplot(data= df_medal_clean, aes(x=rec_mem_neg_mood)) + geom_histogram()+facet_grid(cols=vars(condition))

Centred Distribution
ggplot(data= df_medal_clean, aes(x=rec_mem_neg_mood_c)) + geom_histogram()+facet_grid(cols=vars(condition))

Negative Remote Memory
describe.by(df_medal_clean$rem_mem_neg_mood, group=df_medal_clean$condition) %>% rbindlist() %>% mutate(vars=c("cont", "rem", "dep"))
Warning: describe.by is deprecated. Please use the describeBy function
Distribution
ggplot(data= df_medal_clean, aes(x=rem_mem_neg_mood)) + geom_histogram()+facet_grid(cols=vars(condition))

Centred Distribution
ggplot(data= df_medal_clean, aes(x=rem_mem_neg_mood_c)) + geom_histogram()+facet_grid(cols=vars(condition))

Main
Effects
A simple linear regression analysis was done to look at the
differences in positive and negative mood ratings per condition.
Linear Mixed Models
for PA and NA
#positive mood
positive_model = lmer(pos_mood ~ condition + (1|subjectcode), data = df_medal_clean)
#negative mood
negative_model = lmer(neg_mood ~ condition + (1|subjectcode), data = df_medal_clean)
asis_output(tab_model (positive_model, negative_model,
show.se = T, show.df = T, show.aic = T, transform = NULL,
show.stat = T, show.std = T,
title = 'Condition Differences Mood Rating', dv.labels = c('PA Scaled', 'NA Scaled') )$knitr)
Condition Differences Mood Rating
|
|
PA Scaled
|
NA Scaled
|
|
Predictors
|
Estimates
|
std. Error
|
std. Beta
|
standardized std. Error
|
CI
|
standardized CI
|
Statistic
|
p
|
df
|
Estimates
|
std. Error
|
std. Beta
|
standardized std. Error
|
CI
|
standardized CI
|
Statistic
|
p
|
df
|
|
(Intercept)
|
7.49
|
0.17
|
0.56
|
0.08
|
7.15 – 7.83
|
0.40 – 0.71
|
43.49
|
<0.001
|
7381.00
|
1.14
|
0.20
|
-0.63
|
0.08
|
0.74 – 1.54
|
-0.79 – -0.47
|
5.63
|
<0.001
|
7377.00
|
|
condition [remitted]
|
-1.12
|
0.22
|
-0.51
|
0.10
|
-1.55 – -0.69
|
-0.71 – -0.32
|
-5.13
|
<0.001
|
7381.00
|
1.43
|
0.26
|
0.58
|
0.10
|
0.93 – 1.93
|
0.38 – 0.78
|
5.57
|
<0.001
|
7377.00
|
|
condition [depressed]
|
-2.90
|
0.26
|
-1.32
|
0.12
|
-3.40 – -2.40
|
-1.55 – -1.10
|
-11.38
|
<0.001
|
7381.00
|
3.68
|
0.30
|
1.49
|
0.12
|
3.10 – 4.27
|
1.26 – 1.73
|
12.29
|
<0.001
|
7377.00
|
|
Random Effects
|
|
σ2
|
2.12
|
2.12
|
|
τ00
|
1.58 subjectcode
|
2.20 subjectcode
|
|
ICC
|
0.43
|
0.51
|
|
N
|
191 subjectcode
|
191 subjectcode
|
|
Observations
|
7386
|
7382
|
|
Marginal R2 / Conditional R2
|
0.233 / 0.560
|
0.295 / 0.653
|
|
AIC
|
27174.561
|
27219.514
|
Plot
#create boxplot for negative and positive affect for each group with significance levels
combine_data = df_medal_clean %>%
tidyr::pivot_longer(cols=c(pos_mood, neg_mood), names_to = 'mood_type', values_to = 'mood_rating') %>%
dplyr::mutate(mood_type = factor(mood_type, levels = c('pos_mood' , 'neg_mood')))
# Plot
lm_plot = ggplot(combine_data, aes(x=condition, y = mood_rating, fill= condition)) +
geom_boxplot() +
labs(x ='Group', y ='Affect (scaled units)' ) +
scale_x_discrete(labels = c('control' = 'Never Depressed', 'remitted' = 'Remitted', 'depressed' = 'Depressed' )) +
facet_wrap( ~ mood_type, ncol =3, nrow = 2, labeller = labeller(mood_type = c('pos_mood' = 'Positive Affect', 'neg_mood' = 'Negative Affect'))) +
geom_signif(comparisons = list(c('control', 'remitted'), c('control' , 'depressed'), c('remitted' , 'depressed' )), map_signif_level = T, y_position = c(15, 13, 11)) +
scale_fill_manual(values = wesanderson::wes_palette(n=3, name='GrandBudapest2' )) +
theme_apa() +
guides(fill=F)
ggplotly(lm_plot)
ggsave('plot_simple_regression.pdf', dpi = 320, width = 12, height = 8, path = "figures/")

Follow-Up
emmeans::emmeans(positive_model, pairwise ~ condition, pbkrtest.limit = 7800, lmerTest.limit=7800)
$emmeans
condition emmean SE df lower.CL upper.CL
control 7.49 0.172 188 7.15 7.83
remitted 6.37 0.135 188 6.10 6.63
depressed 4.59 0.188 187 4.21 4.96
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
$contrasts
contrast estimate SE df t.ratio p.value
control - remitted 1.12 0.219 188 5.129 <.0001
control - depressed 2.90 0.255 188 11.381 <.0001
remitted - depressed 1.78 0.232 188 7.696 <.0001
Degrees-of-freedom method: kenward-roger
P value adjustment: tukey method for comparing a family of 3 estimates
emmeans::emmeans(negative_model, pairwise ~ condition, pbkrtest.limit = 7800, lmerTest.limit=7800)
$emmeans
condition emmean SE df lower.CL upper.CL
control 1.14 0.202 188 0.74 1.54
remitted 2.57 0.158 188 2.26 2.88
depressed 4.82 0.221 188 4.39 5.26
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
$contrasts
contrast estimate SE df t.ratio p.value
control - remitted -1.43 0.257 188 -5.571 <.0001
control - depressed -3.68 0.300 188 -12.290 <.0001
remitted - depressed -2.25 0.272 188 -8.282 <.0001
Degrees-of-freedom method: kenward-roger
P value adjustment: tukey method for comparing a family of 3 estimates
Exploratory
Analyses
Moderated Mediation
RemPA-CurrPA
df_medal_moderation = df_medal_clean_remote %>%
filter(!(is.na(pos_mood) | is.na(rem_mem_pos_mood_lag)))
#mediation first
med_fit_h2_pos_rem <- lme4::lmer(rem_mem_pos_mood_lag ~ condition_dummy +
age + gender + education +
(1 |subjectcode),
data =df_medal_moderation)
# full model
out_fit_h2_pos_rem <-lme4::lmer(pos_mood ~ condition_dummy + rem_mem_pos_mood_lag
+ age + gender +education +
(1 + rem_mem_pos_mood_lag |subjectcode),
data=df_medal_moderation)
Warning: Model failed to converge with max|grad| = 0.00602257 (tol = 0.002, component 1)
#mediation analysis for control and remitted
med_pos_rem_rem <- mediation::mediate(med_fit_h2_pos_rem, out_fit_h2_pos_rem,
treat = 'condition_dummy' , control.value = 1, treat.value = 2 , mediator = 'rem_mem_pos_mood_lag')
summary(med_pos_rem_rem)
Causal Mediation Analysis
Quasi-Bayesian Confidence Intervals
Mediator Groups: subjectcode
Outcome Groups: subjectcode
Output Based on Overall Averages Across Groups
Estimate 95% CI Lower 95% CI Upper p-value
ACME (control) -0.663 -0.980 -0.36 <2e-16 ***
ACME (treated) -0.663 -0.980 -0.36 <2e-16 ***
ADE (control) -0.369 -0.680 -0.07 0.012 *
ADE (treated) -0.369 -0.680 -0.07 0.012 *
Total Effect -1.032 -1.453 -0.63 <2e-16 ***
Prop. Mediated (control) 0.643 0.420 0.91 <2e-16 ***
Prop. Mediated (treated) 0.643 0.420 0.91 <2e-16 ***
ACME (average) -0.663 -0.980 -0.36 <2e-16 ***
ADE (average) -0.369 -0.680 -0.07 0.012 *
Prop. Mediated (average) 0.643 0.420 0.91 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Sample Size Used: 771
Simulations: 1000
#create new dataframes with only control remitted and only control depressed
df_medal_con_rem = df_medal_clean %>% filter(condition=='control' | condition == 'remitted')
df_medal_con_dep = df_medal_clean %>% filter(condition=='control' | condition == 'depressed')
#remitted group
df_medal_con_rem$condition_dummy = build_contrast(df_medal_con_rem$condition, 'control', 'remitted')
med_h2_pos_rem_rem <- mdt_moderated(data = df_medal_con_rem, IV =condition_dummy, DV = pos_mood, M = rem_mem_pos_mood_lag, Mod = pos_mood_lag_rem)
rbindlist(med_h2_pos_rem_rem$paths, idcol = T)
NA
RemNA - CurrNA
df_medal_moderation = df_medal_clean_remote %>% filter(!(is.na(neg_mood) | is.na(rem_mem_neg_mood_lag)))
#mediation first
med_fit_h2_neg_rem <- lme4::lmer(rem_mem_neg_mood_lag ~ condition_dummy +
age + gender + education +
(1 |subjectcode),
control = lmerControl(calc.derivs = F, optimizer='bobyqa', optCtrl=list(maxfun=1e6)),
data =df_medal_moderation)
out_fit_h2_neg_rem <-lme4::lmer(neg_mood ~ condition_dummy + rem_mem_neg_mood_lag +
age + gender + education +
(1 + rem_mem_neg_mood_lag |subjectcode),
control = lmerControl(calc.derivs = F, optimizer='bobyqa', optCtrl=list(maxfun=1e6)),
data=df_medal_moderation)
#mediation analysis for control and depressed
med_neg_rem_dep <- mediation::mediate(med_fit_h2_neg_rem, out_fit_h2_neg_rem,
mediator = 'rem_mem_neg_mood_lag', treat = 'condition_dummy' ,
control.value = 1, treat.value = 3 , sims=10000)
summary(med_neg_rem_dep)
Causal Mediation Analysis
Quasi-Bayesian Confidence Intervals
Mediator Groups: subjectcode
Outcome Groups: subjectcode
Output Based on Overall Averages Across Groups
Estimate 95% CI Lower 95% CI Upper p-value
ACME (control) 2.350 1.881 2.85 <2e-16 ***
ACME (treated) 2.350 1.881 2.85 <2e-16 ***
ADE (control) 1.223 0.787 1.66 <2e-16 ***
ADE (treated) 1.223 0.787 1.66 <2e-16 ***
Total Effect 3.573 3.001 4.13 <2e-16 ***
Prop. Mediated (control) 0.657 0.557 0.76 <2e-16 ***
Prop. Mediated (treated) 0.657 0.557 0.76 <2e-16 ***
ACME (average) 2.350 1.881 2.85 <2e-16 ***
ADE (average) 1.223 0.787 1.66 <2e-16 ***
Prop. Mediated (average) 0.657 0.557 0.76 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Sample Size Used: 770
Simulations: 10000
#mediation analysis for control and remitted
med_neg_rem_rem <- mediation::mediate(med_fit_h2_neg_rem, out_fit_h2_neg_rem, treat = 'condition_dummy' , control.value = 1, treat.value = 2 , mediator = 'rem_mem_neg_mood_lag', sims=10000)
summary(med_neg_rem_rem)
Causal Mediation Analysis
Quasi-Bayesian Confidence Intervals
Mediator Groups: subjectcode
Outcome Groups: subjectcode
Output Based on Overall Averages Across Groups
Estimate 95% CI Lower 95% CI Upper p-value
ACME (control) 0.894 0.546 1.27 <2e-16 ***
ACME (treated) 0.894 0.546 1.27 <2e-16 ***
ADE (control) 0.424 0.142 0.70 0.0032 **
ADE (treated) 0.424 0.142 0.70 0.0032 **
Total Effect 1.318 0.886 1.76 <2e-16 ***
Prop. Mediated (control) 0.678 0.505 0.87 <2e-16 ***
Prop. Mediated (treated) 0.678 0.505 0.87 <2e-16 ***
ACME (average) 0.894 0.546 1.27 <2e-16 ***
ADE (average) 0.424 0.142 0.70 0.0032 **
Prop. Mediated (average) 0.678 0.505 0.87 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Sample Size Used: 770
Simulations: 10000
#create new dataframes with only control remitted and only control depressed
df_medal_con_rem = df_medal_clean %>% filter(condition=='control' | condition == 'remitted')
df_medal_con_dep = df_medal_clean %>% filter(condition=='control' | condition == 'depressed')
#remitted group
df_medal_con_rem$condition_dummy = build_contrast(df_medal_con_rem$condition, 'control', 'remitted')
med_h2_neg_rem_rem <- mdt_moderated(data = df_medal_con_rem, IV = condition_dummy, DV = neg_mood, M = rem_mem_neg_mood_lag, Mod = neg_mood_lag_rem)
rbindlist(med_h2_neg_rem_rem$paths, idcol = T)
#depressed group
df_medal_con_dep$condition_dummy = build_contrast(df_medal_con_dep$condition, 'control', 'depressed')
med_h2_neg_rem_dep <- mdt_moderated(data = df_medal_con_dep, IV = condition_dummy, DV = neg_mood, M = rem_mem_neg_mood_lag, Mod = neg_mood_lag_rem)
rbindlist(med_h2_neg_rem_dep$paths,idcol = T)
NA
Context
asis_output(tab_model( (lmer(pos_mood_cs ~ rec_mem_pos_mood_cs_lag*context_location + (1 | subjectcode), data = df_medal_clean)),
(lmer(pos_mood_cs ~ rem_mem_pos_mood_cs_lag*context_location + (1 | subjectcode), data = df_medal_clean)),
(lmer(neg_mood_cs ~ rem_mem_neg_mood_cs_lag*context_location + (1 | subjectcode), data = df_medal_clean)),
(lmer(neg_mood_cs ~ rem_mem_neg_mood_cs_lag*context_location + (1 | subjectcode), data = df_medal_clean)))$knitr)
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
|
|
pos mood cs
|
pos mood cs
|
neg mood cs
|
neg mood cs
|
|
Predictors
|
Estimates
|
CI
|
p
|
Estimates
|
CI
|
p
|
Estimates
|
CI
|
p
|
Estimates
|
CI
|
p
|
|
(Intercept)
|
3.80
|
3.44 – 4.15
|
<0.001
|
5.35
|
4.64 – 6.05
|
<0.001
|
4.77
|
4.11 – 5.44
|
<0.001
|
4.77
|
4.11 – 5.44
|
<0.001
|
|
rec mem pos mood cs lag
|
0.49
|
0.44 – 0.54
|
<0.001
|
|
|
|
|
|
|
|
|
|
|
context location
|
0.01
|
-0.13 – 0.14
|
0.906
|
-0.25
|
-0.53 – 0.02
|
0.068
|
-0.19
|
-0.44 – 0.06
|
0.136
|
-0.19
|
-0.44 – 0.06
|
0.136
|
rec mem pos mood cs lag * context location
|
0.01
|
-0.01 – 0.03
|
0.538
|
|
|
|
|
|
|
|
|
|
|
rem mem pos mood cs lag
|
|
|
|
0.33
|
0.21 – 0.45
|
<0.001
|
|
|
|
|
|
|
rem mem pos mood cs lag * context location
|
|
|
|
0.05
|
0.01 – 0.10
|
0.023
|
|
|
|
|
|
|
|
rem mem neg mood cs lag
|
|
|
|
|
|
|
0.26
|
0.14 – 0.39
|
<0.001
|
0.26
|
0.14 – 0.39
|
<0.001
|
rem mem neg mood cs lag * context location
|
|
|
|
|
|
|
0.04
|
-0.01 – 0.08
|
0.129
|
0.04
|
-0.01 – 0.08
|
0.129
|
|
Random Effects
|
|
σ2
|
1.28
|
1.48
|
1.45
|
1.45
|
|
τ00
|
0.00 subjectcode
|
0.00 subjectcode
|
0.00 subjectcode
|
0.00 subjectcode
|
|
N
|
191 subjectcode
|
188 subjectcode
|
188 subjectcode
|
188 subjectcode
|
|
Observations
|
3146
|
789
|
789
|
789
|
|
Marginal R2 / Conditional R2
|
0.257 / NA
|
0.163 / NA
|
0.100 / NA
|
0.100 / NA
|
SRET
In addition to the EMA, participants also completed the SRET. This is
a lab based memory bias measure. We want to check whether our memory
bias measures from real-life are linked to ones from the lab in this
supplementary analysis.
library('haven')
Warning: package ‘haven’ was built under R version 4.2.3
sret_file = file.path("Z:/", "inbox", "transfer-2023-12-07-02-15-pm", 'MEDAL_pre and post quest and remote recall_workfile!!_for paper only var.sav')
sret_data = read_sav(sret_file)
sret_data = sret_data %>% select(c(1,4)) %>% distinct()
df_medal_rec_cor1 = df_medal_clean %>%
dplyr::select(subjectcode, pos_mood, rec_mem_pos_mood_lag) %>%
na.omit() %>%
dplyr::group_by(subjectcode) %>%
dplyr::mutate(corr = tryCatch(cor(rec_mem_pos_mood_lag, pos_mood), warning = function(e) NA),
model_type = "PA_REC") %>%
dplyr::select(subjectcode, corr, model_type) %>%
dplyr::distinct() %>% ungroup()
df_medal_rec_cor2 = df_medal_clean %>%
dplyr::select(subjectcode, neg_mood, rec_mem_neg_mood_lag) %>%
na.omit() %>%
dplyr::group_by(subjectcode) %>%
dplyr::mutate(corr = tryCatch(cor(rec_mem_neg_mood_lag, neg_mood), warning = function(e) NA),
model_type = "NA_REC") %>%
dplyr::select(subjectcode, corr, model_type) %>%
dplyr::distinct() %>% ungroup()
df_medal_rem_cor1 = df_medal_clean %>%
dplyr::select(subjectcode, pos_mood, rem_mem_pos_mood_lag) %>%
na.omit() %>%
dplyr::group_by(subjectcode) %>%
dplyr::mutate(corr = tryCatch(cor(rem_mem_pos_mood_lag, pos_mood), warning = function(e) NA),
model_type = "PA_REM") %>%
dplyr::select(subjectcode, corr, model_type) %>%
dplyr::distinct()
df_medal_rem_cor2 = df_medal_clean %>%
dplyr::select(subjectcode, neg_mood, rem_mem_neg_mood_lag) %>%
na.omit() %>%
dplyr::group_by(subjectcode) %>%
dplyr::mutate(corr = tryCatch(cor(rem_mem_neg_mood_lag, neg_mood), warning = function(e) NA),
model_type = "NA_REM") %>%
dplyr::select(subjectcode, corr, model_type) %>%
dplyr::distinct()
df_cors = rbindlist(list(df_medal_rec_cor1, df_medal_rec_cor2, df_medal_rem_cor1, df_medal_rem_cor2))
df_ref = merge(sret_data, df_cors, by.x = 'subject', by.y = 'subjectcode')
df_ref = df_ref %>% rename(SRET = SRET_BiasGotlib_neg) %>% dplyr::mutate(group = ifelse(subject<800, "remitted",
ifelse(subject>=900, "control", 'depressed')) )
for (mod_type in c("PA_REC", "PA_REM", "NA_REC", "NA_REM")){
print(mod_type)
print(summary(lm(SRET ~ corr*group, data = df_ref %>% filter(model_type == mod_type))))
}
[1] "PA_REC"
Call:
lm(formula = SRET ~ corr * group, data = df_ref %>% filter(model_type ==
mod_type))
Residuals:
Min 1Q Median 3Q Max
-0.42802 -0.18783 -0.03731 0.07877 0.96612
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.032066 0.055434 0.578 0.5637
corr 0.009979 0.109528 0.091 0.9275
groupdepressed 0.207749 0.113678 1.828 0.0694 .
groupremitted 0.109699 0.078769 1.393 0.1655
corr:groupdepressed 0.299086 0.203331 1.471 0.1431
corr:groupremitted 0.145614 0.151633 0.960 0.3383
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.2605 on 171 degrees of freedom
(14 observations deleted due to missingness)
Multiple R-squared: 0.2304, Adjusted R-squared: 0.2079
F-statistic: 10.24 on 5 and 171 DF, p-value: 1.343e-08
[1] "PA_REM"
Call:
lm(formula = SRET ~ corr * group, data = df_ref %>% filter(model_type ==
mod_type))
Residuals:
Min 1Q Median 3Q Max
-0.41550 -0.21434 -0.03978 0.12018 0.96298
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.034360 0.044794 0.767 0.444147
corr 0.008142 0.065661 0.124 0.901462
groupdepressed 0.365632 0.065231 5.605 8.57e-08 ***
groupremitted 0.192437 0.056284 3.419 0.000792 ***
corr:groupdepressed 0.007906 0.096231 0.082 0.934621
corr:groupremitted -0.025126 0.082845 -0.303 0.762047
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.2675 on 165 degrees of freedom
(17 observations deleted due to missingness)
Multiple R-squared: 0.2043, Adjusted R-squared: 0.1802
F-statistic: 8.475 on 5 and 165 DF, p-value: 3.685e-07
[1] "NA_REC"
Call:
lm(formula = SRET ~ corr * group, data = df_ref %>% filter(model_type ==
mod_type))
Residuals:
Min 1Q Median 3Q Max
-0.45379 -0.17704 -0.03939 0.08131 0.96345
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.03215 0.04477 0.718 0.473691
corr 0.01727 0.10065 0.172 0.863976
groupdepressed 0.29548 0.08311 3.555 0.000489 ***
groupremitted 0.10471 0.06401 1.636 0.103709
corr:groupdepressed 0.14637 0.15930 0.919 0.359496
corr:groupremitted 0.18205 0.13735 1.325 0.186793
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.2605 on 170 degrees of freedom
(15 observations deleted due to missingness)
Multiple R-squared: 0.2323, Adjusted R-squared: 0.2097
F-statistic: 10.29 on 5 and 170 DF, p-value: 1.249e-08
[1] "NA_REM"
Call:
lm(formula = SRET ~ corr * group, data = df_ref %>% filter(model_type ==
mod_type))
Residuals:
Min 1Q Median 3Q Max
-0.43367 -0.17164 -0.04881 0.12752 0.94467
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.04423 0.04128 1.071 0.285714
corr -0.02001 0.06467 -0.309 0.757395
groupdepressed 0.34096 0.06427 5.305 3.86e-07 ***
groupremitted 0.19828 0.05408 3.667 0.000338 ***
corr:groupdepressed 0.08919 0.10774 0.828 0.409041
corr:groupremitted -0.07917 0.08544 -0.927 0.355620
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.2702 on 154 degrees of freedom
(28 observations deleted due to missingness)
Multiple R-squared: 0.2103, Adjusted R-squared: 0.1846
F-statistic: 8.201 on 5 and 154 DF, p-value: 6.88e-07
Relative Bias
Here we want to check for the relative NA/PA bias. So we extact the
random effects from the models to get the slopes for each subject, and
then compare the NA/PA slopes. This tells us if theres a bias between
negative and positive memory.
# Get individual slopes
pos_rec_ref = as.data.frame(ranef(h1_pos_recent_models[[2]])) %>% filter(term!='(Intercept)') %>% select(c(3:5))
pos_rem_ref = as.data.frame(ranef(h1_pos_remote_models[[2]])) %>% filter(term!='(Intercept)') %>% select(c(3:5))
neg_rec_ref = as.data.frame(ranef(h1_neg_recent_models[[4]])) %>% filter(term!='(Intercept)') %>% select(c(3:5))
neg_rem_ref = as.data.frame(ranef(h1_neg_remote_models[[4]])) %>% filter(term!='(Intercept)') %>% select(c(3:5))
pos_rec_ref$mod = "PA_REC"
pos_rem_ref$mod = "PA_REM"
neg_rec_ref$mod = "NA_REC"
neg_rem_ref$mod = "NA_REM"
# Put together into a new data frame
df_ref = rbindlist(list(pos_rec_ref, pos_rem_ref, neg_rec_ref, neg_rem_ref))
df_ref = df_ref %>%
dplyr::mutate(sub = as.numeric(as.character(grp))) %>%
dplyr::mutate(group = ifelse(sub <= 800, "remitted",
ifelse(sub>=900, "control", 'depressed')) )
df_ref_rec = df_ref %>% filter(mod == 'PA_REC' | mod=='NA_REC')
df_ref_rem = df_ref %>% filter(mod == 'PA_REM' | mod=='NA_REM')
summary(lmer(condsd ~ mod*group + (1|sub), data = df_ref_rec))
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: condsd ~ mod * group + (1 | sub)
Data: df_ref_rec
REML criterion at convergence: -1628.1
Scaled residuals:
Min 1Q Median 3Q Max
-5.2099 -0.1327 0.0034 0.2821 2.0044
Random effects:
Groups Name Variance Std.Dev.
sub (Intercept) 7.503e-05 0.008662
Residual 5.543e-04 0.023543
Number of obs: 370, groups: sub, 185
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 0.174483 0.003446 358.898081 50.636 < 2e-16 ***
modPA_REC -0.151757 0.004573 182.000000 -33.182 < 2e-16 ***
groupdepressed -0.031232 0.005055 358.898081 -6.178 1.76e-09 ***
groupremitted -0.019837 0.004381 358.898081 -4.528 8.11e-06 ***
modPA_REC:groupdepressed 0.028693 0.006709 182.000000 4.277 3.06e-05 ***
modPA_REC:groupremitted 0.018448 0.005814 182.000000 3.173 0.00177 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Correlation of Fixed Effects:
(Intr) mdPA_REC grpdpr grprmt mdPA_REC:grpd
modPA_REC -0.664
groupdprssd -0.682 0.452
groupremttd -0.787 0.522 0.536
mdPA_REC:grpd 0.452 -0.682 -0.664 -0.356
mdPA_REC:grpr 0.522 -0.787 -0.356 -0.664 0.536
summary(lmer(condsd ~ mod*group + (1|sub), data = df_ref_rem))
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: condsd ~ mod * group + (1 | sub)
Data: df_ref_rem
REML criterion at convergence: -3053.2
Scaled residuals:
Min 1Q Median 3Q Max
-4.6559 -0.3184 0.0410 0.5489 1.7622
Random effects:
Groups Name Variance Std.Dev.
sub (Intercept) 2.596e-06 0.001611
Residual 9.576e-06 0.003094
Number of obs: 368, groups: sub, 184
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 4.997e-02 4.792e-04 3.463e+02 104.265 < 2e-16 ***
modPA_REM -1.178e-02 6.011e-04 1.810e+02 -19.601 < 2e-16 ***
groupdepressed 6.628e-05 7.030e-04 3.463e+02 0.094 0.9249
groupremitted -1.069e-04 6.106e-04 3.463e+02 -0.175 0.8612
modPA_REM:groupdepressed -3.553e-03 8.818e-04 1.810e+02 -4.029 8.22e-05 ***
modPA_REM:groupremitted -1.525e-03 7.659e-04 1.810e+02 -1.991 0.0479 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Correlation of Fixed Effects:
(Intr) mdPA_REM grpdpr grprmt mdPA_REM:grpd
modPA_REM -0.627
groupdprssd -0.682 0.428
groupremttd -0.785 0.492 0.535
mdPA_REM:grpd 0.428 -0.682 -0.627 -0.336
mdPA_REM:grpr 0.492 -0.785 -0.336 -0.627 0.535
Plots
First we set our theme and fix the data for the figures we want
# Theme
ggtheme = theme(text = element_text(size = 8),
panel.background = element_rect(fill = "transparent"),
panel.grid.major = element_line(color = "grey90"),
panel.grid.minor = element_line(color = "grey100"),
panel.border = element_rect(color = "grey80", fill = "transparent"))
# Estimate the SD
df_medal_clean2 = df_medal_clean %>%
mutate(pos_mood_sd = ifelse( (pos_mood_cs_lag_rec > (mean(pos_mood_cs_lag_rec, na.rm=T)+sd(pos_mood_cs_lag_rec, na.rm=T))), "+1SD",
ifelse( (pos_mood_cs_lag_rec < (mean(pos_mood_cs_lag_rec, na.rm=T)-sd(pos_mood_cs_lag_rec, na.rm =T))), "-1SD", "Mean"))) %>%
mutate(neg_mood_sd = ifelse( (neg_mood_cs_lag_rec > (mean(neg_mood_cs_lag_rec, na.rm=T)+sd(neg_mood_cs_lag_rec, na.rm=T))), "+1SD",
ifelse( (neg_mood_cs_lag_rec < (mean(neg_mood_cs_lag_rec, na.rm=T)-sd(neg_mood_cs_lag_rec, na.rm =T))), "-1SD", "Mean")))
# Fix factor levels
df_medal_clean2$Condition = factor(df_medal_clean2$condition, levels=c('control', 'remitted', 'depressed' ), labels=c('Never-Depressed', 'Remitted', 'Depressed'))
df_medal_clean2$pos_mood_sd = factor(df_medal_clean2$pos_mood_sd, levels=c('-1SD', 'Mean', '+1SD' ))
df_medal_clean2$neg_mood_sd = factor(df_medal_clean2$neg_mood_sd, levels=c('-1SD', 'Mean', '+1SD' ))
PA-CUR-REC
# Plot
plot_pa_rec = ggplot(df_medal_clean2, aes(x = rec_mem_pos_mood_c_lag, y=pos_mood_c, color = pos_mood_sd, fill = pos_mood_sd)) +
geom_smooth(method = 'lm', alpha = 0.15) +
labs( x = bquote(paste(REC[PA], " (subject-centered a.u.)")), y = "PA (subject-centered a.u.)", color = bquote(CUR[PA]), fill = bquote(CUR[PA]) ) +
ggtheme +
scale_color_manual(values = wesanderson::wes_palette(n=3, name='GrandBudapest2' )) +
scale_fill_manual(values = wesanderson::wes_palette(n=3, name='GrandBudapest2' )) +
facet_grid(.~Condition)
plot_pa_rec

PA-CUR-REC
# Plot
plot_na_rec =
ggplot(df_medal_clean2, aes(x = rec_mem_neg_mood_c_lag, y=neg_mood_c, color = neg_mood_sd, fill = neg_mood_sd)) +
geom_smooth(method = 'lm', alpha = 0.15) +
labs( x = bquote(paste(REC['NA'], " (subject-centered a.u.)")), y = "NA (subject-centered a.u.)", color = bquote(CUR["NA"]), fill = bquote(CUR["NA"]) ) +
scale_color_manual(values = wesanderson::wes_palette(n=3, name='GrandBudapest2' )) +
scale_fill_manual(values = wesanderson::wes_palette(n=3, name='GrandBudapest2' )) +
ggtheme +
facet_grid(.~Condition)
plot_na_rec

Combined Plot for
pub
ggarrange(NA, plot_pa_rec, NA, plot_na_rec,
widths=c(0.05, 1, 0.05, 1), ncol = 2, nrow = 2,
labels=c("A", NA, "B"))
Warning: Cannot convert object of class logical into a grob.`geom_smooth()` using formula = 'y ~ x'Warning: Removed 4247 rows containing non-finite values (`stat_smooth()`).Warning: Cannot convert object of class logical into a grob.`geom_smooth()` using formula = 'y ~ x'Warning: Removed 4249 rows containing non-finite values (`stat_smooth()`).
ggsave("figures/fig1_threeway.pdf", device = 'pdf', dpi = 320, height = 6)
Saving 7.3 x 6 in image

LS0tDQp0aXRsZTogJ0Vtb3Rpb25hbCBNZW1vcnkgaW4gRGFpbHkgTGlmZScNCmF1dGhvcjoNCi0gTm9hIE1hZ3VzaW4NCi0gUmF5eWFuIFR1dHVuamkNCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgICBmaWdfd2lkdGg6IDgNCiAgICBmaWdfaGVpZ2h0OiA4DQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdGhlbWU6IGZsYXRseQ0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQotLS0NCg0KIyBJbnRyb2R1Y3Rpb24NCg0KVGhpcyBub3RlYm9vayBjb250YWlucyBhbmFseXNlcyBmcm9tIHRoZSBNRURBTCBzdHVkeSwgYXNzZXNzaW5nIG1lbW9yeSBiaWFzIGluIHJlbWl0dGVkIGFuZCBkZXByZXNzZWQgaW5kaXZpZHVhbHMuIFRoZSBwcmUtcmVnaXN0cmF0aW9uIGZvciB0aGUgbWFpbiBhbmFseXNlcywgYXMgd2VsbCBhcyBhIHByZXByaW50IHZlcnNpb24gb2YgdGhlIGFjY29tcGFueWluZyBhcnRpY2xlIGNhbiBiZSBmb3VuZCBbaGVyZV0oaHR0cHM6Ly9vc2YuaW8venVmanMvKSBhcyB3ZWxsLiBUaGUgbWFpbiBhaW0gb2YgdGhlIGN1cnJlbnQgd29yayB3YXMgdG8gZXhhbWluZSBob3cgdGhyZWUgZ3JvdXBzIChjb250cm9sLCByZW1pdHRlZCwgZGVwcmVzc2VkKSBkaWZmZXIgaW4gdGVybXMgb2YgZW1vdGlvbmFsIG1lbW9yeSBkeW5hbWljcyBpbiBhIHJlYWwtbGlmZSBzZXR0aW5nLg0KDQpgYGB7ciBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQojTG9hZCBwYWNrYWdlcyANCiNyZW52OjphY3RpdmF0ZSgpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShqYW5pdG9yKQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KGRhdGEudGFibGUpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHBzeWNoKQ0KbGlicmFyeShkZXZ0b29scykNCmxpYnJhcnkocGFzdGVjcykNCmxpYnJhcnkoY2xpKQ0KbGlicmFyeShsbWVyVGVzdCkgI2xpbmVhciBtaXhlZCBtb2RlbHMgDQpsaWJyYXJ5KHBlcmZvcm1hbmNlKSAjZml0cyBvZiByZXNpZHVhbHMgDQpsaWJyYXJ5KERlc2NUb29scykNCmxpYnJhcnkodGlkeXIpICMgU2VwYXJhdGUgdHJpZ2dlciBjb2x1bW4NCmxpYnJhcnkoc2pQbG90KSAjIGZvciBuaWNlIHRhYmxlcyBhbmQgaW50ZXJhY3Rpb24gcGxvdHMgDQpsaWJyYXJ5KGtuaXRyKSAjIHRvIHByaW50IHRoZSB0YWJsZXMgd2l0aGluIG5vdGVib29rDQpsaWJyYXJ5KGZvcmVhY2gpICNydW4gcGFyYWxsZWwgbG9vcHMNCmxpYnJhcnkocGFyYWxsZWwpDQpsaWJyYXJ5KGRvUGFyYWxsZWwpICNydW4gcGFyYWxsZWwgbG9vcHMNCmxpYnJhcnkoZ2dwdWJyKSAjIGVtbWVhbnMNCmxpYnJhcnkobWVkaWF0aW9uKSAjbWVkaWF0aW9uIGFuYWx5c2lzIA0KbGlicmFyeShwbG90bHkpICNmb3IgaW50ZXJhY3RpdmUgcGxvdHMNCmxpYnJhcnkoanRvb2xzKSAjZm9yIHRoZW1lX2FwYQ0KbGlicmFyeShKU21lZGlhdGlvbikgI21vZGVyYXRlZCBtZWRpYXRpb24NCmxpYnJhcnkod2VzYW5kZXJzb24pIA0Kc291cmNlKCJmdW5jdGlvbnMuUiIpDQpgYGANCg0KIyBEYXRhDQoNCkhlcmUgd2UgbG9hZCBpbiBvdXIgZGF0YSBhbmQgcHJlcHJvY2VzcyBpdCBpbiBzdGVwcy4gV2UgZmlyc3QgbmVlZCB0byBzZXBhcmF0ZSB0aGUgZGlmZmVyZW50IHN1cnZleXMgdGhhdCB3ZXJlIGRlbGl2ZXJlZCB0byBicmluZyB0aGVtIGludG8gdGhlIHNhbWUgc2FtcGxpbmcgdGltZXMsIG1lcmdlIGluIHNvbWUgZGVzY3JpcHRpdmVzIHdlIG5lZWQgYXMgY292YXJpYXRlcywgYW5kIGVzdGltYXRlIHN1YmplY3QtY2VudGVyZWQgYW5kIGxhZ2dlZCB2YXJpYWJsZXMgZm9yIG91ciBtb2RlbHMgbGF0ZXIuIA0KDQoNCjEuIExvYWQgYW5kIGNsZWFuIGRhdGENCg0KYGBge3J9DQojIExvYWQgdGhlIGRhdGENCk1FREFMX0VTTV9jb21wbGVldCA8LSByZWFkX2V4Y2VsKCJkYXRhL01FREFMX0VTTV9jb21wbGVldC54bHN4IikNCiMgTW92ZSB2YXJpYWJsZXMgYXJvdW5kIGFuZCBjbGVhbiBuYW1lcw0KTUVEQUxfRVNNX2NvbXBsZWV0PSBNRURBTF9FU01fY29tcGxlZXQgJT4lDQogIHJlbmFtZShpZD0nTW92aXNlbnMtSUQnKSAlPiUgDQogIGNsZWFuX25hbWVzKCkgJT4lDQogIHJlbmFtZShzdWJqZWN0Y29kZSA9ICdkZWVsbmVtZXJzbnInKSAlPiUgDQogIHJlbG9jYXRlKCdzdWJqZWN0Y29kZScsIC5hZnRlciA9ICdpZCcpDQpkZl9tZWRhbF90cnkgPSBNRURBTF9FU01fY29tcGxlZXQNCg0KYGBgDQoNCjIuIFNwbGl0IGRpZmZlcmVudCBFTUEgc3VydmV5cyB3ZSBoYXZlDQoNCmBgYHtyfQ0KIyBTbGVlcCBFTUEgUXMNCmRmX21lZGFsX3NsZWVwID0gZGZfbWVkYWxfdHJ5ICU+JSANCiAgZmlsdGVyKGZvcm09PSdTbGFhcCcpICU+JSANCiAgZHBseXI6OnNlbGVjdChjKDEsIDIsIDQsIDUsIDcsIDksIDE0KSkgDQojIFJlY2VudCBFTUEgUXMNCmRmX21lZGFsX3JlY2VudCA9IGRmX21lZGFsX3RyeSAlPiUgDQogIGZpbHRlcihmb3JtPT0nUmVjZW50JykgJT4lIA0KICBkcGx5cjo6c2VsZWN0KGMoMSwgMiwgNCwgNSwgNywgOSwgY29udGFpbnMoJ3JlYycpKSkNCiMgUmVtb3RlIEVNQSBRcw0KZGZfbWVkYWxfcmVtb3RlID0gZGZfbWVkYWxfdHJ5ICU+JQ0KICBmaWx0ZXIoZm9ybT09J1JlbW90ZScpICU+JQ0KICBkcGx5cjo6c2VsZWN0KGMoMSwgMiwgNCwgNSwgNywgOSwgY29udGFpbnMoJ3JlbScpKSkNCiMgTWFzdGVyeSBFTUEgUXMNCmRmX21lZGFsX21hc3RlcnkgPSBkZl9tZWRhbF90cnkgJT4lDQogIGZpbHRlcihmb3JtPT0nTWFzdGVyeScpICU+JSANCiAgZHBseXI6OnNlbGVjdChjKDEsIDIsIDQsIDUsIDcsIDksIGNvbnRhaW5zKCdtYXN0ZXInKSkpDQojIFN0YW5kYXJkIFFzDQpkZl9tZWRhbF9zdGFuZGFyZCA9IGRmX21lZGFsX3RyeSAlPiUNCiAgZmlsdGVyKGZvcm09PSdTdGFuZGFhcmQnKSAgJT4lDQogIGRwbHlyOjpzZWxlY3QoYygxLCAyLCA0LCA1LCA3LCA5LCAoLWNvbnRhaW5zKCdtYXN0ZXJ5JykgJiAtY29udGFpbnMoJ3JlbScpICYgLWNvbnRhaW5zKCdyZWMnKSkpKSAlPiUgDQogIGRwbHlyOjpzZWxlY3QoLWMoNywxMywxNCkpDQoNCiMgbWVyZ2Ugc2xlZXAgYW5kIHN0YW5kYXJkDQpkZl9tZWRhbF9tZXJnZWQgPSBtZXJnZShkZl9tZWRhbF9zbGVlcCwgZGZfbWVkYWxfc3RhbmRhcmQsIGJ5PWMoJ2lkJywgJ3RyaWdnZXJfY291bnRlcicsICdzdWJqZWN0Y29kZScpLCBzdWZmaXhlcyA9IGMoIl9zbGVlcCIsICIiKSwgYWxsPVQgKQ0KDQojIG1lcmdlIHRvIHJlY2VudCwgcmVtb3RlIGFuZCBtYXN0ZXJ5DQpkZl9tZWRhbF9tZXJnZWQ9IG1lcmdlKGRmX21lZGFsX21lcmdlZCwgZGZfbWVkYWxfcmVjZW50LCBieT1jKCdpZCcsICd0cmlnZ2VyX2NvdW50ZXInLCAnc3ViamVjdGNvZGUnICksIHN1ZmZpeGVzID0gYygnJywgJ19yZWNlbnQnKSwgYWxsID0gVCApDQpkZl9tZWRhbF9tZXJnZWQgPSBtZXJnZShkZl9tZWRhbF9tZXJnZWQsIGRmX21lZGFsX3JlbW90ZSwgYnk9YygnaWQnLCAndHJpZ2dlcl9jb3VudGVyJywgJ3N1YmplY3Rjb2RlJyApLCBzdWZmaXhlcyA9IGMoJycsICdfcmVtb3RlJyksIGFsbCA9IFQgKQ0KZGZfbWVkYWxfbWVyZ2VkID0gbWVyZ2UoZGZfbWVkYWxfbWVyZ2VkLCBkZl9tZWRhbF9tYXN0ZXJ5LCBieT1jKCdpZCcsICd0cmlnZ2VyX2NvdW50ZXInLCAnc3ViamVjdGNvZGUnICksIHN1ZmZpeGVzID0gYygnJywgJ19tYXN0ZXJ5JyksIGFsbCA9IFQgKQ0KDQojIEZpeCBzdGFydCBkYXRlcyBhbmQgdGltZXMNCmRmX21lZGFsX21lcmdlZCRmb3JtX3N0YXJ0X2RhdGUgPC0gYXMuY2hhcmFjdGVyKGRmX21lZGFsX21lcmdlZCRmb3JtX3N0YXJ0X2RhdGUpDQpkZl9tZWRhbF9tZXJnZWQkZm9ybV9zdGFydF9kYXRlIDwtIGFzLklUaW1lKGRmX21lZGFsX21lcmdlZCRmb3JtX3N0YXJ0X2RhdGUpDQpkZl9tZWRhbF9tZXJnZWQgPSBkZl9tZWRhbF9tZXJnZWQgJT4lIA0KICBkcGx5cjo6bXV0YXRlKGZvcm1fc3RhcnRfZGF0ZSA9IGlmZWxzZShpcy5uYShmb3JtX3N0YXJ0X2RhdGUpLCBmb3JtX3N0YXJ0X2RhdGVfc2xlZXAsIGZvcm1fc3RhcnRfZGF0ZSkpDQpgYGANCg0KMy4gQWRkIHZhcmlhYmxlcyBvbiBFZHVjYXRpb24sIEdlbmRlciwgYW5kIEFnZQ0KDQpgYGB7cn0NCiMgTG9hZCBpbiBwcmV2aW91cyBkYXRhIGZvciBkZW1vZ3JhcGhpY3MgKGFsc28gY29udGFpbnMgRU1BKQ0KbG9hZCgiZGF0YS9JUEFRX01hZXZlX1dvcmtzcGFjZS5SRGF0YSIpDQpkZl9NRURBTCA8LSBkZl9NRURBTFstYygxOTIpLCBdDQoNCiMgU2VsZWN0IHJlbGV2YW50IGRlbW8gaW5mbw0KZGZfTUVEQUwgPSBkZl9NRURBTCAlPiUgDQogIGRwbHlyOjpzZWxlY3QoMSwgMywgNTo3KSAlPiUgDQogIHJlbmFtZSgnc3ViamVjdGNvZGUnID0gJ3N1YmplY3QnLCAnZWR1Y2F0aW9uJyA9ICdFZHVjYXRpb24zZ3JvdXBzJywgJ25fZXBpc29kZXMnPSdOdW1iZXJFcGlzb2RlcycgKQ0KDQojIG1lcmdlIGRlbW8gdG8gZnVsbCBFTUENCmRmX21lZGFsX21lcmdlZCA9ICBtZXJnZShkZl9tZWRhbF9tZXJnZWQsIGRmX01FREFMLCBieSA9IGMoJ3N1YmplY3Rjb2RlJyksIGFsbCA9IFQgKSAlPiUNCiAgY2xlYW5fbmFtZXMoKSANCg0KZGZfbWVkYWxfbWVyZ2VkJGVkdWNhdGlvbiA9IGFzLmZhY3RvcihkZl9tZWRhbF9tZXJnZWQkZWR1Y2F0aW9uKQ0KZGZfbWVkYWxfbWVyZ2VkJGdlbmRlciA9IGFzLmZhY3RvcihkZl9tZWRhbF9tZXJnZWQkZ2VuZGVyKQ0KDQpkZl9tZWRhbF9tZXJnZWQgPSBkZl9tZWRhbF9tZXJnZWQgJT4lIA0KICByZWxvY2F0ZShjKCdpZCcsICdnZW5kZXInLCAnYWdlJywgJ2VkdWNhdGlvbicpLCAuYWZ0ZXIgPSAnc3ViamVjdGNvZGUnKSAlPiUgDQogIHJlbG9jYXRlICgnYWdlJywgLmFmdGVyID0gJ2dlbmRlcicpICU+JSANCiAgcmVsb2NhdGUgKCdlZHVjYXRpb24nLCAuYWZ0ZXIgPSAnYWdlJykgJT4lIA0KICByZWxvY2F0ZSAoJ2lkJywgLmJlZm9yZSA9ICdzdWJqZWN0Y29kZScpDQoNCmBgYA0KDQo0LiBDYXRlZ29yaXplIHRoZSBzdWJqZWN0Y29kZSBpbnRvIHRoZSB0aHJlZSBjb25kaXRpb25zIChEZXByZXNzZWQsIFJlbWl0dGVkLCBDb250cm9sIChOZXZlci1kZXByZXNzZWQpKQ0KDQpgYGB7cn0NCmRmX21lZGFsX21lcmdlZCRjb25kaXRpb24gPSBjYXNlX3doZW4oZGZfbWVkYWxfbWVyZ2VkJHN1YmplY3Rjb2RlID49IDcwMCAmIGRmX21lZGFsX21lcmdlZCRzdWJqZWN0Y29kZSA8IDgwMCB+ICJyZW1pdHRlZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRmX21lZGFsX21lcmdlZCRzdWJqZWN0Y29kZSA+PSA4MDAgJiBkZl9tZWRhbF9tZXJnZWQkc3ViamVjdGNvZGUgPCA5MDAgfiAiZGVwcmVzc2VkIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRmX21lZGFsX21lcmdlZCRzdWJqZWN0Y29kZSA+PSA5MDAgfiAiY29udHJvbCIpDQpkZl9tZWRhbF9tZXJnZWQgPSBkZl9tZWRhbF9tZXJnZWQgJT4lIHJlbG9jYXRlICgnY29uZGl0aW9uJywgLmFmdGVyID0gJ3N1YmplY3Rjb2RlJyApDQpkZl9tZWRhbF9tZXJnZWQkY29uZGl0aW9uIDwtIGFzLmZhY3RvcihkZl9tZWRhbF9tZXJnZWQkY29uZGl0aW9uKQ0KYGBgDQoNCjUuIENhbGN1bGF0ZSByZWFjdGlvbiB0aW1lIA0KDQpgYGB7cn0NCmRmX21lZGFsX21lcmdlZCRydF9zbGVlcCA9IGx1YnJpZGF0ZTo6YXMuZGlmZnRpbWUoIGRmX21lZGFsX21lcmdlZCRmb3JtX2ZpbmlzaF9kYXRlX3NsZWVwIC0gZGZfbWVkYWxfbWVyZ2VkJGZvcm1fc3RhcnRfZGF0ZV9zbGVlcCkNCmBgYA0KDQo2LiBTZXBhcmF0ZSB0aW1lIGZyb20gd2hlbiB0cmlnZ2VyIHdhcyBzZW50DQoNCmBgYHtyfQ0KDQpkZl9tZWRhbF9tZXJnZWQgPSBkZl9tZWRhbF9tZXJnZWQgJT4lIA0KICB0aWR5cjo6c2VwYXJhdGUodHJpZ2dlciwgYygnUmFuZG9tJywgJ1RpbWUnLCAnVHJpZ2dlcl9UaW1lXzEnLCAnVHJpZ2dlcl9UaW1lXzInKSkgICU+JSANCiAgZHBseXI6Om11dGF0ZSh0cmlnZ2VyX3RpbWUgPSBwYXN0ZShUcmlnZ2VyX1RpbWVfMSwgVHJpZ2dlcl9UaW1lXzIsIHNlcD0nOicpKSAlPiUjc2VwYXJhdGUgdGltZSBmcm9tIHByZXZpb3VzIHRyaWdnZXINCiAgZHBseXI6Om11dGF0ZSh0cmlnZ2VyID0gcGFzdGUoUmFuZG9tLCBUaW1lLCB0cmlnZ2VyX3RpbWUsIHNlcD0nICcpKSAjYnJpbmcgYmFjayAndHJpZ2dlcicgY29sdW1uIA0KDQojVHVybiBudW1iZXJzIGludG8gdGltZSBmb3JtYXQNCmRmX21lZGFsX21lcmdlZCR0cmlnZ2VyX3RpbWUgPC0gYXMuSVRpbWUoZGZfbWVkYWxfbWVyZ2VkJHRyaWdnZXJfdGltZSkNCmBgYA0KDQo3LiBGaW5kIHRoZSB0cmlnZ2VyIG51bWJlciBwZXIgZGF5DQoNCmBgYHtyfQ0KI2RmX21lZGFsX21lcmdlZCR0cmlnZ2VyX2NvdW50ZXJbaXMubmEoZGZfbWVkYWxfbWVyZ2VkJHRyaWdnZXJfdGltZSldIDwtIDENCg0KZGZfbWVkYWxfbWVyZ2VkJHRyaWdnZXJfbnVtYmVyW2lzLm5hKGRmX21lZGFsX21lcmdlZCR0cmlnZ2VyX3RpbWUpXSA8LSAxIA0KZGZfbWVkYWxfbWVyZ2VkJHRyaWdnZXJfbnVtYmVyW2RmX21lZGFsX21lcmdlZCR0cmlnZ2VyX3RpbWUgPj0gKGFzLklUaW1lKCIxMDowMDowMCIpKSYgZGZfbWVkYWxfbWVyZ2VkJHRyaWdnZXJfdGltZSA8IChhcy5JVGltZSgiMTI6MDA6MDAiKSldIDwtIDINCmRmX21lZGFsX21lcmdlZCR0cmlnZ2VyX251bWJlcltkZl9tZWRhbF9tZXJnZWQkdHJpZ2dlcl90aW1lID49IChhcy5JVGltZSgiMTI6MDA6MDAiKSkmIGRmX21lZGFsX21lcmdlZCR0cmlnZ2VyX3RpbWUgPCAoYXMuSVRpbWUoIjE0OjAwOjAwIikpXSA8LSAzDQpkZl9tZWRhbF9tZXJnZWQkdHJpZ2dlcl9udW1iZXJbZGZfbWVkYWxfbWVyZ2VkJHRyaWdnZXJfdGltZSA+PSAoYXMuSVRpbWUoIjE0OjAwOjAwIikpJiBkZl9tZWRhbF9tZXJnZWQkdHJpZ2dlcl90aW1lIDwgKGFzLklUaW1lKCIxNjowMDowMCIpKV0gPC0gNA0KZGZfbWVkYWxfbWVyZ2VkJHRyaWdnZXJfbnVtYmVyW2RmX21lZGFsX21lcmdlZCR0cmlnZ2VyX3RpbWUgPj0gKGFzLklUaW1lKCIxNjowMDowMCIpKSYgZGZfbWVkYWxfbWVyZ2VkJHRyaWdnZXJfdGltZSA8IChhcy5JVGltZSgiMTg6MDA6MDAiKSldIDwtIDUNCmRmX21lZGFsX21lcmdlZCR0cmlnZ2VyX251bWJlcltkZl9tZWRhbF9tZXJnZWQkdHJpZ2dlcl90aW1lID49IChhcy5JVGltZSgiMTg6MDA6MDAiKSkmIGRmX21lZGFsX21lcmdlZCR0cmlnZ2VyX3RpbWUgPCAoYXMuSVRpbWUoIjIwOjAwOjAwIikpXSA8LSA2DQpkZl9tZWRhbF9tZXJnZWQkdHJpZ2dlcl9udW1iZXJbZGZfbWVkYWxfbWVyZ2VkJHRyaWdnZXJfdGltZSA+PSAoYXMuSVRpbWUoIjIwOjAwOjAwIikpJiBkZl9tZWRhbF9tZXJnZWQkdHJpZ2dlcl90aW1lIDwgKGFzLklUaW1lKCIyMzowMDowMSIpKV0gPC0gNw0KDQojIGRmDQpkZl9tZWRhbF9tZXJnZWQgPSBkZl9tZWRhbF9tZXJnZWQgJT4lIA0KICByZWxvY2F0ZSAoJ3RyaWdnZXJfbnVtYmVyJywgLmFmdGVyID0gJ3RyaWdnZXJfY291bnRlcicpJT4lIHJlbG9jYXRlKCd0cmlnZ2VyX3RpbWUnLCAuYmVmb3JlID0nZm9ybV9zdGFydF9kYXRlJykgJT4lDQogIHJlbG9jYXRlKCd0cmlnZ2VyJywgLmJlZm9yZSA9J3RyaWdnZXJfdGltZScpDQpgYGANCg0KOC4gRmluYWwgY2xlYW5pbmcgb2YgdGhlIGRhdGFzZXQNCmBgYHtyfQ0KDQojQ3JlYXRlIGRhdGFzZXQgd2hlcmUgZG91YmxlIG1vcm5pbmcgbGlzdCBpcyByZW1vdmVkIA0KZGZfbWVkYWxfbWVyZ2VkID0gZGZfbWVkYWxfbWVyZ2VkICU+JSANCiAgZHBseXI6Om11dGF0ZSh0cmlnZ2VyX2NvdW50ZXI9aWZlbHNlKHRyaWdnZXJfbnVtYmVyPT0xICYgbGFnKHRyaWdnZXJfbnVtYmVyKT09MSwgbGFnKHRyaWdnZXJfY291bnRlciksIHRyaWdnZXJfY291bnRlcikpICU+JSANCiAgZHBseXI6Om11dGF0ZSh0cmlnZ2VyX2NvdW50ZXI9aWZlbHNlKHRyaWdnZXJfbnVtYmVyPT0xICYgbGFnKHRyaWdnZXJfbnVtYmVyKT09MSwgbGFnKHRyaWdnZXJfY291bnRlciksIHRyaWdnZXJfY291bnRlcikpICU+JQ0KICBkcGx5cjo6bXV0YXRlKHRyaWdnZXJfY291bnRlcj1pZmVsc2UodHJpZ2dlcl9udW1iZXI9PTEgJiBsYWcodHJpZ2dlcl9udW1iZXIpPT0xLCBsYWcodHJpZ2dlcl9jb3VudGVyKSwgdHJpZ2dlcl9jb3VudGVyKSkgJT4lDQogIGRwbHlyOjptdXRhdGUodHJpZ2dlcl9jb3VudGVyPWlmZWxzZSh0cmlnZ2VyX251bWJlcj09MSAmIGxhZyh0cmlnZ2VyX251bWJlcik9PTEsIGxhZyh0cmlnZ2VyX2NvdW50ZXIpLCB0cmlnZ2VyX2NvdW50ZXIpKSAlPiUgDQogIGRwbHlyOjptdXRhdGUodHJpZ2dlcl9jb3VudGVyPWlmZWxzZSh0cmlnZ2VyX251bWJlcj09MSAmIGxhZyh0cmlnZ2VyX251bWJlcik9PTEsIGxhZyh0cmlnZ2VyX2NvdW50ZXIpLCB0cmlnZ2VyX2NvdW50ZXIpKQ0KDQojIG5vdyB3ZSBoYXZlIHRoZSBjbGVhbiBkYXRhZnJhbWUsIHJlbW92ZSBkdXBsaWNhdGVkIGNvbG91bW5zDQpkZl9tZWRhbF9jbGVhbiA9IGRmX21lZGFsX21lcmdlZCAlPiUNCiAgZHBseXI6Omdyb3VwX2J5KHN1YmplY3Rjb2RlKSAlPiUgDQogIGRpc3RpbmN0KHRyaWdnZXJfY291bnRlciwgLmtlZXBfYWxsID0gVFJVRSkgJT4lIA0KICBkcGx5cjo6c2VsZWN0ICgxOjEyLCAxNzo2MCkgJT4lIA0KICBkcGx5cjo6bXV0YXRlKG9yaWdpbmFsX29yZGVyID0gcm93X251bWJlcigpKSAlPiUgDQogIHJlbG9jYXRlKCdvcmlnaW5hbF9vcmRlcicsIC5iZWZvcmUgPSAnaWQnKQ0KDQojU2V0IHRoZSBvcmRlciBvZiB0aGUgZmFjdG9yIHRvIGNvbnRyb2wsIHJlbWlzc2lvbiwgZGVwcmVzc2lvbiAoZm9yIHZpc3VhbCBwdXJwb3NlcykNCmRmX21lZGFsX2NsZWFuJGNvbmRpdGlvbiA8LSBmYWN0b3IoZGZfbWVkYWxfY2xlYW4kY29uZGl0aW9uLCBsZXZlbHM9YygnY29udHJvbCcsICdyZW1pdHRlZCcsICdkZXByZXNzZWQnICksIGxhYmVscz1jKCdjb250cm9sJywgJ3JlbWl0dGVkJywgJ2RlcHJlc3NlZCcpKQ0KDQojIENyZWF0ZSBkdW1teSB2YXJpYWJsZSANCmRmX21lZGFsX2NsZWFuID0gZGZfbWVkYWxfY2xlYW4gJT4lIA0KICBtdXRhdGUoY29uZGl0aW9uX2R1bW15ID0gY2FzZV93aGVuKGNvbmRpdGlvbiA9PSAnZGVwcmVzc2VkJ34gMywgY29uZGl0aW9uID09ICdyZW1pdHRlZCd+IDIsIGNvbmRpdGlvbiA9PSAnY29udHJvbCcgfiAxKSkNCg0KZGZfbWVkYWxfY2xlYW4kY29uZGl0aW9uX2R1bW15ID0gYXMuZmFjdG9yKGRmX21lZGFsX2NsZWFuJGNvbmRpdGlvbl9kdW1teSkNCg0KI3NldCB3ZWVrZGF5IA0KZGZfbWVkYWxfY2xlYW4kZm9ybV9maW5pc2hfZGF0ZSA8LSBhcy5jaGFyYWN0ZXIoZGZfbWVkYWxfY2xlYW4kZm9ybV9maW5pc2hfZGF0ZSkNCmRmX21lZGFsX2NsZWFuJGZvcm1fZmluaXNoX2RhdGUgPC0gc3RycHRpbWUoZGZfbWVkYWxfY2xlYW4kZm9ybV9maW5pc2hfZGF0ZSwgZm9ybWF0ID0gJyVZLSVtLSVkICVIOiVNOiVTJykNCg0KZGZfbWVkYWxfY2xlYW4kZmluaXNoX2RhdGUgPC0gYXMuRGF0ZShkZl9tZWRhbF9jbGVhbiRmb3JtX2ZpbmlzaF9kYXRlKQ0KZGZfbWVkYWxfY2xlYW4kd2Vla2RheSA8LSBhcy5pbnRlZ2VyKGZvcm1hdChkZl9tZWRhbF9jbGVhbiRmaW5pc2hfZGF0ZSwgJyV3JykpDQpkZl9tZWRhbF9jbGVhbiA9IGRmX21lZGFsX2NsZWFuICU+JSByZWxvY2F0ZSgnd2Vla2RheScsIC5hZnRlciA9ICd0cmlnZ2VyX251bWJlcicpDQoNCiNzb2x2ZSBkdXBsaWNhdGUgaXNzdWUgDQpkZl9tZWRhbF9kdXBsaWNhdGUgPSBkZl9tZWRhbF9jbGVhbiAlPiUgZHBseXI6Omdyb3VwX2J5KHN1YmplY3Rjb2RlLCB3ZWVrZGF5KSAlPiUgZmlsdGVyKGR1cGxpY2F0ZWQodHJpZ2dlcl9udW1iZXIpKQ0KDQogICNzaW5jZSByb3cgMTAgZm9yIHN1YmplY3QgNzEyIGlzIGEgZHVwbGljYXRlIG1vcm5pbmcgbGlzdA0KICBkZl9tZWRhbF9jbGVhbiA8LSBzdWJzZXQoZGZfbWVkYWxfY2xlYW4sICEoc3ViamVjdGNvZGUgPT0gNzEyICYgb3JpZ2luYWxfb3JkZXIgPT0gMTApKQ0KICBkZl9tZWRhbF9jbGVhbiA9IGRmX21lZGFsX2NsZWFuICU+JSBkcGx5cjo6Z3JvdXBfYnkoc3ViamVjdGNvZGUsIHdlZWtkYXkpICU+JSANCiAgICBtdXRhdGUodGVtcCA9IGxlYWQodHJpZ2dlcl9udW1iZXIpLCANCiAgICAgICAgICAgdHJpZ2dlcl9udW1iZXIgPSBjYXNlX3doZW4odHJpZ2dlcl9udW1iZXIgPT0gdGVtcCB+ICh0ZW1wIC0xKSwgVFJVRSB+IHRyaWdnZXJfbnVtYmVyKSkgJT4lDQogICAgc2VsZWN0KC10ZW1wKQ0KICAjVGFrZSB0aGUgcm93cyBvdXQgdGhhdCBoYXZlICdOQSdmb3IgdGhlIHdlZWtkYXkgc2luY2UgZm9ybSB3YXNuJ3QgZmluaXNoZWQgYW5kIHRoZXJlIGlzIG5vIGRhdGEgZm9yIFBBLCBOQSwgb3IgTWVtb3J5DQogIGRmX21lZGFsX2NsZWFuID0gZGZfbWVkYWxfY2xlYW4gJT4lIGZpbHRlcighaXMubmEod2Vla2RheSkpDQogIGRmX21lZGFsX2NsZWFuJG9yaWdpbmFsX29yZGVyIDwtIDE6bnJvdyhkZl9tZWRhbF9jbGVhbikgDQoNCiMgQ3JlYXRlIGV4cGFuZGVkIGRmIHdpdGggYWxsIHBvdGVudGlhbCBkYXRhcG9pbnRzDQoNCmRmX21lZGFsX2RheSA9IGRmX21lZGFsX2NsZWFuICU+JSANCiAgZHBseXI6OnNlbGVjdCgnc3ViamVjdGNvZGUnLCAnd2Vla2RheScsICdvcmlnaW5hbF9vcmRlcicpICU+JSANCiAgZHBseXI6Om11dGF0ZSh3ZWVrZGF5ID0gYXMubnVtZXJpYyh3ZWVrZGF5KSkgJT4lDQogIGRwbHlyOjpncm91cF9ieShzdWJqZWN0Y29kZSkgJT4lDQogIGRwbHlyOjogZGlzdGluY3Qod2Vla2RheSwgLmtlZXBfYWxsID1UKSAlPiUgDQogIGRwbHlyOjp1bmdyb3VwKCkNCg0KZGZfbWVkYWxfZGF5ID0gZGZfbWVkYWxfZGF5ICU+JSANCiAgc2xpY2UocmVwKDE6bigpLCBlYWNoID0gNykpICU+JSANCiAgZHBseXI6Om11dGF0ZSh0cmlnZ2VyX251bWJlciA9IHJlcCgxOjcsIGxlbmd0aC5vdXQ9bigpKSkgJT4lIA0KICBkcGx5cjo6cmVuYW1lKG9yZGVyID0gb3JpZ2luYWxfb3JkZXIpDQoNCg0KI21lcmdlIHdpdGggbWFpbiBkYXRhZnJhbWUNCmRmX21lZGFsX2NsZWFuID0gIG1lcmdlKGRmX21lZGFsX2RheSwgZGZfbWVkYWxfY2xlYW4sIGJ5PWMoJ3N1YmplY3Rjb2RlJywgJ3RyaWdnZXJfbnVtYmVyJywgJ3dlZWtkYXknKSwgYWxsPSBUKSANCmRmX21lZGFsX2NsZWFuID0gZGZfbWVkYWxfY2xlYW4gJT4lIG11dGF0ZShvcmRlciA9IGFzLm51bWVyaWMob3JkZXIpKQ0KZGZfbWVkYWxfY2xlYW4gPSBhcnJhbmdlKGRmX21lZGFsX2NsZWFuLCBvcmRlcikNCmBgYA0KDQo5LiBDZW50cmUsIHNjYWxlLCBhbmQgYXZlcmFnZSBWYXJpYWJsZXMgDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0V9DQoNCnVzZWRfdmFycyA9IGMoIm5lZ19tb29kIiwgInJlY19tZW1fbmVnX21vb2QiLCAicmVtX21lbV9uZWdfbW9vZCIsICJwb3NfbW9vZCIsICJyZWNfbWVtX3Bvc19tb29kIiwgInJlbV9tZW1fcG9zX21vb2QiKQ0KDQojQ2VudGVyaW5nICYgc2NhbGluZyANCmRmX21lZGFsX2NsZWFuID0gZGZfbWVkYWxfY2xlYW4gJT4lIA0KICBkcGx5cjo6Z3JvdXBfYnkoc3ViamVjdGNvZGUpICU+JQ0KICAjIENlbnRlciBhbmQgc2NhbGUNCiAgZHBseXI6Om11dGF0ZSggYWNyb3NzKHVzZWRfdmFycywgfiAoLngvMTApLCAubmFtZXMgPSAiey5jb2x9IiApLA0KICAgICAgICAgICAgICAgICBhY3Jvc3ModXNlZF92YXJzLCB+IG1lYW4oLngsIG5hLnJtPVQpLCAubmFtZXMgPSAiey5jb2x9X20iICksDQogICAgICAgICAgICAgICAgIGFjcm9zcyh1c2VkX3ZhcnMsIH4gKC54IC0gbWVhbigueCwgbmEucm09VCkpLCAubmFtZXMgPSAiey5jb2x9X2MiICksIA0KICAgICAgICAgICAgICAgICBhY3Jvc3MocGFzdGUwKHVzZWRfdmFycywgIl9jIiksIH4gRGVzY1Rvb2xzOjpXaW5zb3JpemUoLngsIG5hLnJtID0gVCksIC5uYW1lcyA9ICJ7LmNvbH0iKSkgJT4lICANCiAgdW5ncm91cCgpICU+JQ0KICAjIFJlc2NhbGUgdG8gcG9zaXRpdmUNCiAgbXV0YXRlKGFjcm9zcyhjKHBhc3RlMCh1c2VkX3ZhcnMsIl9jIikpLCB+IGFicyhtaW4oLngsIG5hLnJtID0gVCkpICsgMSArIC54LCAubmFtZXMgPSAiey5jb2x9cyIpKQ0KDQpgYGANCg0KDQoxMC4gTGFnIHZhcmlhYmxlcyANCmBgYHtyfQ0KIyBSZW1vdGUgDQoNCmRmX21lZGFsX2NsZWFuID0gZGZfbWVkYWxfY2xlYW4gJT4lDQogIGRwbHlyOjpncm91cF9ieShzdWJqZWN0Y29kZSkgJT4lDQogIG11dGF0ZShyZW1fbWVtX3Bvc19tb29kX2xhZyA9IGxlYWQocmVtX21lbV9wb3NfbW9vZCwgbj03LCBvcmRlcl9ieT1zdWJqZWN0Y29kZSksDQogICAgICAgICByZW1fbWVtX25lZ19tb29kX2xhZyA9IGxlYWQocmVtX21lbV9uZWdfbW9vZCwgbj03LCBvcmRlcl9ieT1zdWJqZWN0Y29kZSksDQogICAgICAgICBwb3NfbW9vZF9sYWdfcmVtID0gbGVhZChwb3NfbW9vZCwgbj03LCBvcmRlcl9ieT1zdWJqZWN0Y29kZSksDQogICAgICAgICBuZWdfbW9vZF9sYWdfcmVtID0gbGVhZChuZWdfbW9vZCwgbj03LCBvcmRlcl9ieT1zdWJqZWN0Y29kZSksIA0KICAgICAgICAgcmVtX21lbV9wb3NfbW9vZF9jc19sYWcgPSBsZWFkKHJlbV9tZW1fcG9zX21vb2RfY3MsIG49Nywgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgcmVtX21lbV9uZWdfbW9vZF9jc19sYWcgPSBsZWFkKHJlbV9tZW1fbmVnX21vb2RfY3MsIG49Nywgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgcG9zX21vb2RfY3NfbGFnX3JlbSA9IGxlYWQocG9zX21vb2RfY3MsIG49Nywgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgbmVnX21vb2RfY3NfbGFnX3JlbSA9IGxlYWQobmVnX21vb2RfY3MsIG49Nywgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgcmVtX21lbV9wb3NfbW9vZF9jX2xhZyA9IGxlYWQocmVtX21lbV9wb3NfbW9vZF9jLCBuPTcsIG9yZGVyX2J5PXN1YmplY3Rjb2RlKSwNCiAgICAgICAgIHJlbV9tZW1fbmVnX21vb2RfY19sYWcgPSBsZWFkKHJlbV9tZW1fbmVnX21vb2RfYywgbj03LCBvcmRlcl9ieT1zdWJqZWN0Y29kZSksDQogICAgICAgICBwb3NfbW9vZF9jX2xhZ19yZW0gPSBsZWFkKHBvc19tb29kX2MsIG49Nywgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgbmVnX21vb2RfY19sYWdfcmVtID0gbGVhZChuZWdfbW9vZF9jLCBuPTcsIG9yZGVyX2J5PXN1YmplY3Rjb2RlKSkgJT4lIA0KICBmaWx0ZXIoIWlzLm5hKG9yaWdpbmFsX29yZGVyKSkgIyBmaWx0ZXIgb3V0IHRoZSBOQSByb3dzIGZvciB0aGUgbGFnZ2luZyBvZiByZWNlbnQgbWVtb3J5IA0KDQojIFJlY2VudA0KZGZfbWVkYWxfY2xlYW4gPSBkZl9tZWRhbF9jbGVhbiAlPiUgDQogIGRwbHlyOjpncm91cF9ieShzdWJqZWN0Y29kZSkgJT4lDQogIG11dGF0ZShyZWNfbWVtX3Bvc19tb29kX2xhZyA9IGxlYWQocmVjX21lbV9wb3NfbW9vZCwgbj0xLCBvcmRlcl9ieT1zdWJqZWN0Y29kZSksDQogICAgICAgICByZWNfbWVtX25lZ19tb29kX2xhZyA9IGxlYWQocmVjX21lbV9uZWdfbW9vZCwgbj0xLCBvcmRlcl9ieT1zdWJqZWN0Y29kZSksDQogICAgICAgICBwb3NfbW9vZF9sYWdfcmVjID0gbGVhZChwb3NfbW9vZCwgbj0xLCBvcmRlcl9ieT1zdWJqZWN0Y29kZSksDQogICAgICAgICBuZWdfbW9vZF9sYWdfcmVjID0gbGVhZChuZWdfbW9vZCwgbj0xLCBvcmRlcl9ieT1zdWJqZWN0Y29kZSksDQogICAgICAgICByZWNfbWVtX3Bvc19tb29kX2NzX2xhZyA9IGxlYWQocmVjX21lbV9wb3NfbW9vZF9jcywgbj0xLCBvcmRlcl9ieT1zdWJqZWN0Y29kZSksDQogICAgICAgICByZWNfbWVtX25lZ19tb29kX2NzX2xhZyA9IGxlYWQocmVjX21lbV9uZWdfbW9vZF9jcywgbj0xLCBvcmRlcl9ieT1zdWJqZWN0Y29kZSksDQogICAgICAgICBwb3NfbW9vZF9jc19sYWdfcmVjID0gbGVhZChwb3NfbW9vZF9jcywgbj0xLCBvcmRlcl9ieT1zdWJqZWN0Y29kZSksDQogICAgICAgICBuZWdfbW9vZF9jc19sYWdfcmVjID0gbGVhZChuZWdfbW9vZF9jcywgbj0xLCBvcmRlcl9ieT1zdWJqZWN0Y29kZSksDQogICAgICAgICByZWNfbWVtX3Bvc19tb29kX2NfbGFnID0gbGVhZChyZWNfbWVtX3Bvc19tb29kX2MsIG49MSwgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgcmVjX21lbV9uZWdfbW9vZF9jX2xhZyA9IGxlYWQocmVjX21lbV9uZWdfbW9vZF9jLCBuPTEsIG9yZGVyX2J5PXN1YmplY3Rjb2RlKSwNCiAgICAgICAgIHBvc19tb29kX2NfbGFnX3JlYyA9IGxlYWQocG9zX21vb2RfYywgbj0xLCBvcmRlcl9ieT1zdWJqZWN0Y29kZSksDQogICAgICAgICBuZWdfbW9vZF9jX2xhZ19yZWMgPSBsZWFkKG5lZ19tb29kX2MsIG49MSwgb3JkZXJfYnk9c3ViamVjdGNvZGUpKSAlPiUgDQogIHVuZ3JvdXAoKQ0KICANCg0KYGBgDQoNCiMgRGVzY3JpcHRpdmVzIHsudGFic2V0fQ0KDQpXZSBmaXJzdCBwbG90IHNvbWUgZ2VuZXJhbCBwb3B1bGF0aW9uIGRlc2NyaXB0aXZlcywgZm9sbG93ZWQgYnkgc29tZSBkZXNjcmlwdGl2ZXMgb2YgdGhlIHNjYWxlcyB3ZSB1c2UgaW4gdGhlIEVNQSB3ZWVrcyBhbmQgY29tcGxpYW5jZSByYXRlcy4NCg0KIyMgUG9wdWxhdGlvbiBEZXNjcmlwdGl2ZXMgey19DQpgYGB7ciBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MjB9DQojQ3JlYXRlIERlc2NyaXB0aXZlcyBUYWJsZXMNCnN1bW1hcnlfdGFibGUgPSBkZl9tZWRhbF9jbGVhbiAlPiUgZGlzdGluY3Qoc3ViamVjdGNvZGUsIC5rZWVwX2FsbCA9IFRSVUUpICU+JSBncm91cF9ieShjb25kaXRpb24pICU+JSBzdW1tYXJpc2UoDQogICdOJyA9IG4oKSwNCiAgJ0FnZSBcbiBNICsvLSBTRCcgPSBwYXN0ZTAocm91bmQobWVhbihhZ2UsIG5hLnJtID1UKSwgMSksICcgKy8tICcgLCByb3VuZChzZChhZ2UsIG5hLnJtID1UKSwgMSkpLA0KICAjJ05BIEFnZScgPSBzdW0oaXMubmEoYWdlKSksIA0KICAnJSBFZHVjYXRpb24gTG93JyA9IG1lYW4oZWR1Y2F0aW9uID09IDAsIG5hLnJtID0gVCkqMTAwLA0KICAnJSBFZHVjYXRpb24gTWlkZGxlJyA9IG1lYW4oZWR1Y2F0aW9uID09IDEsIG5hLnJtID0gVCkqMTAwLA0KICAnJSBFZHVjYXRpb24gSGlnaCcgPSBtZWFuKGVkdWNhdGlvbiA9PSAyLCBuYS5ybSA9IFQpKjEwMCwNCiAgIydOQSBFZHVjYXRpb24nID0gc3VtKGlzLm5hKGVkdWNhdGlvbikpLCANCiAgJyUgRmVtYWxlJyA9IG1lYW4oZ2VuZGVyID09MSwgbmEucm0gPSBUKSoxMDAsDQogICMnTkEgR2VuZGVyJyA9IHN1bShpcy5uYShnZW5kZXIpKQ0KKQ0KDQojQ29tcGxpYW5jZSByYXRlcw0KZGZfbWVkYWxfY29tcGxpYW5jZV9pbmRpdmlkdWFsID0gZGZfbWVkYWxfY2xlYW4gJT4lIGdyb3VwX2J5KGNvbmRpdGlvbiwgc3ViamVjdGNvZGUpICU+JSBzdW1tYXJpc2UoJ0NvbXBsaWFuY2VSYXRlJyA9IHN1bSghaXMubmEodHJpZ2dlcl9udW1iZXIpKS80MioxMDApDQoNCmxlbmd0aCh3aGljaChkZl9tZWRhbF9jb21wbGlhbmNlX2luZGl2aWR1YWwkQ29tcGxpYW5jZVJhdGUgPDcwKSkNCg0KZGZfbWVkYWxfY29tcGxpYW5jZSA9IGRmX21lZGFsX2NsZWFuICU+JSBncm91cF9ieShjb25kaXRpb24pICU+JSBzdW1tYXJpc2UoJyUgTWVhbiBDb21wbGlhbmNlJyA9IHN1bSghaXMubmEodHJpZ2dlcl9udW1iZXIpKS8obl9kaXN0aW5jdChzdWJqZWN0Y29kZSkgKjQyKSoxMDApIA0KDQoNCiMgQ3JlYXRlIGEgdGFibGUNCnN1bW1hcnlfdGFibGUgPSBzdW1tYXJ5X3RhYmxlICU+JSBsZWZ0X2pvaW4oZGZfbWVkYWxfY29tcGxpYW5jZSwgYnkgPSAnY29uZGl0aW9uJykNCnJlbXBzeWM6Om5pY2VfdGFibGUoc3VtbWFyeV90YWJsZSkNCg0KDQojY3JlYXRlIGRhdGFzZXQgd2l0aCBvbmx5IHVuaXF1ZSBzdWJqZWN0Y29kZSANCmRmX21lZGFsX2Rpc3RpbmN0ID0gZGZfbWVkYWxfY2xlYW4gJT4lIGRpc3RpbmN0KHN1YmplY3Rjb2RlLCAua2VlcF9hbGwgPSBUUlVFKSU+JSBzZWxlY3QoJ3N1YmplY3Rjb2RlJywgJ2NvbmRpdGlvbicsICdhZ2UnLCAnZWR1Y2F0aW9uJywgJ2dlbmRlcicpDQoNCiNUZXN0IGZvciBkaWZmZXJlbmNlcyBiZXR3ZWVuIGdyb3VwcyANCiAgI0FnZQ0KICBkZl9tZWRhbF9kaXN0aW5jdCAlPiUgbG0oYWdlIH4gY29uZGl0aW9uLCBkYXRhPS4pICU+JSBzdW1tYXJ5KCkNCiAgDQogICNlZHVjYXRpb24NCiAgY2hpc3EudGVzdChkZl9tZWRhbF9kaXN0aW5jdCRlZHVjYXRpb24sIGRmX21lZGFsX2Rpc3RpbmN0JGNvbmRpdGlvbikNCiAgDQogICNnZW5kZXINCiAgY2hpc3EudGVzdChkZl9tZWRhbF9kaXN0aW5jdCRnZW5kZXIsIGRmX21lZGFsX2Rpc3RpbmN0JGNvbmRpdGlvbikNCiAgDQojQ3JlYXRlIGEgR3JhcGggIA0KICAjYWdlDQogIGJveHBsb3RfYWdlIDwtIGdncGxvdChkZl9tZWRhbF9kaXN0aW5jdCwgYWVzKHg9Y29uZGl0aW9uLCB5PWFnZSwgZmlsbD1jb25kaXRpb24pKSArDQogICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgIGxhYnMoeCA9ICdDb25kaXRpb24nLCB5ID0gJ0FnZScsIHRhZyA9ICdDJyApICsNCiAgICBnZ3RpdGxlKCdBZ2UgcGVyIENvbmRpdGlvbicpICsNCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB3ZXNhbmRlcnNvbjo6d2VzX3BhbGV0dGUobj0zLCBuYW1lPSdHcmFuZEJ1ZGFwZXN0MicgKSkgICsNCiAgICB0aGVtZV9hcGEoKSANCiAgZ2dwbG90bHkoYm94cGxvdF9hZ2UpDQogICAgDQogICAgI2VkdWNhdGlvbg0KICAgIHBsb3RfZWR1YyA8LSBnZ3Bsb3QoZGZfbWVkYWxfZGlzdGluY3QsIGFlcyh4PWNvbmRpdGlvbiwgZmlsbCA9IGVkdWNhdGlvbikpICsNCiAgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgICAgbGFicyh4PSdDb25kaXRpb24nLCB5PSAnUHJvcG9ydGlvbicsIHRhZyA9ICdBJyApICsNCiAgICAgIGdndGl0bGUoJ0VkdWNhdGlvbiBMZXZlbCBwZXIgQ29uZGl0aW9uJykgKw0KICAgICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gd2VzYW5kZXJzb246Ondlc19wYWxldHRlKG49MywgbmFtZT0nR3JhbmRCdWRhcGVzdDInICksIGxhYmVscyA9IGMoJ0xvdycgLCAnTWlkZGxlJyAsICdIaWdoJyksIG5hbWUgPSAnRWR1Y2F0aW9uJykgICsNCiAgICAgIHRoZW1lX2FwYSgpIA0KICAgIGdncGxvdGx5KHBsb3RfZWR1YykNCiAgICAgIA0KICAgICNHZW5kZXINCiAgICBwbG90X2dlbmRlciA8LSBnZ3Bsb3QoZGZfbWVkYWxfZGlzdGluY3QsIGFlcyh4PWNvbmRpdGlvbiwgZmlsbCA9IGdlbmRlcikpICsNCiAgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgICAgbGFicyh4ID0gJ0NvbmRpdGlvbicsIHkgPSAnUHJvcG9ydGlvbicsIHRhZyA9ICdCJyApICsNCiAgICAgIGdndGl0bGUoJ0dlbmRlciBwZXIgQ29uZGl0aW9uJykgKw0KICAgICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gd2VzYW5kZXJzb246Ondlc19wYWxldHRlKG49MywgbmFtZT0nR3JhbmRCdWRhcGVzdDInICksIGxhYmVscyA9IGMoJ01hbGUnLCAnRmVtYWxlJyksICdHZW5kZXInKSAgKw0KICAgICAgdGhlbWVfYXBhKCkgDQogICAgZ2dwbG90bHkocGxvdF9nZW5kZXIpDQogICAgICANCiAgICAgcGxvdF9nZW5kZXJfMiA8LSAgZ2dzdGF0c3Bsb3Q6OmdnYmFyc3RhdHMoZGF0YSA9IGRmX21lZGFsX2Rpc3RpbmN0LCB4ID0gZ2VuZGVyLCB5ID0gY29uZGl0aW9uKSArDQogICAgICAgIGxhYnMoeCA9ICdDb25kaXRpb24nLCB5ID0gJ1Byb3BvcnRpb24nLCB0YWcgPSAnQicgKSArDQogICAgICAgIGdndGl0bGUoJ0dlbmRlciBwZXIgQ29uZGl0aW9uJykgKw0KICAgICAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB3ZXNhbmRlcnNvbjo6d2VzX3BhbGV0dGUobj0zLCBuYW1lPSdHcmFuZEJ1ZGFwZXN0MicgKSwgbGFiZWxzID0gYygnTWFsZScsICdGZW1hbGUnKSwgJ0dlbmRlcicpICArDQogICAgICAgIHRoZW1lX2FwYSgpIA0KICAgICAgZ2dwbG90bHkocGxvdF9nZW5kZXJfMikNCg0KZ2dwdWJyOjpnZ2FycmFuZ2UocGxvdF9lZHVjLCBwbG90X2dlbmRlciwgYm94cGxvdF9hZ2UsIG5yb3c9MiwgbmNvbD0yKSAgICANCg0KICAgIA0KYGBgDQojIyBQb3NpdGl2ZSBNb29kIHstfQ0KDQpgYGB7cn0NCmRlc2NyaWJlLmJ5KGRmX21lZGFsX2NsZWFuJHBvc19tb29kLCBncm91cD1kZl9tZWRhbF9jbGVhbiRjb25kaXRpb24pICU+JSByYmluZGxpc3QoKSAlPiUgbXV0YXRlKHZhcnM9YygiY29udCIsICJyZW0iLCAiZGVwIikpDQpgYGANCg0KRGlzdHJpYnV0aW9uDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGE9IGRmX21lZGFsX2NsZWFuLCBhZXMoeD1wb3NfbW9vZCkpICsgZ2VvbV9oaXN0b2dyYW0oKStmYWNldF9ncmlkKGNvbHM9dmFycyhjb25kaXRpb24pKQ0KYGBgIA0KDQpDZW50cmVkIERpc3RyaWJ1dGlvbiANCmBgYHtyfQ0KZ2dwbG90KGRhdGE9IGRmX21lZGFsX2NsZWFuLCBhZXMoeD1wb3NfbW9vZF9jKSkgKyBnZW9tX2hpc3RvZ3JhbSgpK2ZhY2V0X2dyaWQoY29scz12YXJzKGNvbmRpdGlvbikpDQpgYGANCg0KDQojIyBQb3NpdGl2ZSBSZWNlbnQgTWVtb3J5IHstfQ0KDQpgYGB7cn0NCmRlc2NyaWJlLmJ5KGRmX21lZGFsX2NsZWFuJHJlY19tZW1fcG9zX21vb2QsIGdyb3VwPWRmX21lZGFsX2NsZWFuJGNvbmRpdGlvbikgJT4lIHJiaW5kbGlzdCgpICU+JSBtdXRhdGUodmFycz1jKCJjb250IiwgInJlbSIsICJkZXAiKSkNCmBgYA0KDQpEaXN0cmlidXRpb24NCmBgYHtyfQ0KZ2dwbG90KGRhdGE9IGRmX21lZGFsX2NsZWFuLCBhZXMoeD1yZWNfbWVtX3Bvc19tb29kKSkgKyBnZW9tX2hpc3RvZ3JhbSgpK2ZhY2V0X2dyaWQoY29scz12YXJzKGNvbmRpdGlvbikpDQpgYGANCg0KQ2VudHJlZCBEaXN0cmlidXRpb24gDQpgYGB7cn0NCmdncGxvdChkYXRhPSBkZl9tZWRhbF9jbGVhbiwgYWVzKHg9cmVjX21lbV9wb3NfbW9vZF9jKSkgKyBnZW9tX2hpc3RvZ3JhbSgpK2ZhY2V0X2dyaWQoY29scz12YXJzKGNvbmRpdGlvbikpDQpgYGANCg0KDQojIyBQb3NpdGl2ZSBSZW1vdGUgTWVtb3J5IHstfQ0KDQpgYGB7cn0NCmRlc2NyaWJlLmJ5KGRmX21lZGFsX2NsZWFuJHJlbV9tZW1fcG9zX21vb2QsIGdyb3VwPWRmX21lZGFsX2NsZWFuJGNvbmRpdGlvbikgJT4lIHJiaW5kbGlzdCgpICU+JSBtdXRhdGUodmFycz1jKCJjb250IiwgInJlbSIsICJkZXAiKSkNCmBgYA0KDQpEaXN0cmlidXRpb24NCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YT0gZGZfbWVkYWxfY2xlYW4sIGFlcyh4PXJlbV9tZW1fcG9zX21vb2QpKSArIGdlb21faGlzdG9ncmFtKCkrZmFjZXRfZ3JpZChjb2xzPXZhcnMoY29uZGl0aW9uKSkNCmBgYA0KDQpDZW50cmVkIERpc3RyaWJ1dGlvbiANCmBgYHtyfQ0KZ2dwbG90KGRhdGE9IGRmX21lZGFsX2NsZWFuLCBhZXMoeD1yZW1fbWVtX3Bvc19tb29kX2MpKSArIGdlb21faGlzdG9ncmFtKCkrZmFjZXRfZ3JpZChjb2xzPXZhcnMoY29uZGl0aW9uKSkNCmBgYA0KDQoNCiMjIE5lZ2F0aXZlIE1vb2Qgey19DQoNCmBgYHtyfQ0KZGVzY3JpYmUuYnkoZGZfbWVkYWxfY2xlYW4kbmVnX21vb2QsIGdyb3VwPWRmX21lZGFsX2NsZWFuJGNvbmRpdGlvbiklPiUgcmJpbmRsaXN0KCkgJT4lIG11dGF0ZSh2YXJzPWMoImNvbnQiLCAicmVtIiwgImRlcCIpKQ0KDQpgYGANCg0KRGlzdHJpYnV0aW9uDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGE9IGRmX21lZGFsX2NsZWFuLCBhZXMoeD1uZWdfbW9vZCkpICsgZ2VvbV9oaXN0b2dyYW0oKStmYWNldF9ncmlkKGNvbHM9dmFycyhjb25kaXRpb24pKQ0KYGBgDQpDZW50cmVkIERpc3RyaWJ1dGlvbiANCmBgYHtyfQ0KZ2dwbG90KGRhdGE9IGRmX21lZGFsX2NsZWFuLCBhZXMoeD1uZWdfbW9vZF9jKSkgKyBnZW9tX2hpc3RvZ3JhbSgpK2ZhY2V0X2dyaWQoY29scz12YXJzKGNvbmRpdGlvbikpDQpnZ3Bsb3QoZGF0YT0gZGZfbWVkYWxfY2xlYW4sIGFlcyh4PW5lZ19tb29kX2NzKSkgKyBnZW9tX2hpc3RvZ3JhbSgpK2ZhY2V0X2dyaWQoY29scz12YXJzKGNvbmRpdGlvbikpDQpgYGANCg0KDQojIyBOZWdhdGl2ZSBSZWNlbnQgTWVtb3J5IHstfQ0KDQpgYGB7cn0NCmRlc2NyaWJlLmJ5KGRmX21lZGFsX2NsZWFuJHJlY19tZW1fbmVnX21vb2QsIGdyb3VwPWRmX21lZGFsX2NsZWFuJGNvbmRpdGlvbikgJT4lIHJiaW5kbGlzdCgpICU+JSBtdXRhdGUodmFycz1jKCJjb250IiwgInJlbSIsICJkZXAiKSkNCmBgYA0KDQpEaXN0cmlidXRpb24NCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YT0gZGZfbWVkYWxfY2xlYW4sIGFlcyh4PXJlY19tZW1fbmVnX21vb2QpKSArIGdlb21faGlzdG9ncmFtKCkrZmFjZXRfZ3JpZChjb2xzPXZhcnMoY29uZGl0aW9uKSkNCmBgYA0KQ2VudHJlZCBEaXN0cmlidXRpb24gDQpgYGB7cn0NCmdncGxvdChkYXRhPSBkZl9tZWRhbF9jbGVhbiwgYWVzKHg9cmVjX21lbV9uZWdfbW9vZF9jKSkgKyBnZW9tX2hpc3RvZ3JhbSgpK2ZhY2V0X2dyaWQoY29scz12YXJzKGNvbmRpdGlvbikpDQpgYGANCg0KDQojIyBOZWdhdGl2ZSBSZW1vdGUgTWVtb3J5IHstfQ0KDQpgYGB7cn0NCmRlc2NyaWJlLmJ5KGRmX21lZGFsX2NsZWFuJHJlbV9tZW1fbmVnX21vb2QsIGdyb3VwPWRmX21lZGFsX2NsZWFuJGNvbmRpdGlvbikgJT4lIHJiaW5kbGlzdCgpICU+JSBtdXRhdGUodmFycz1jKCJjb250IiwgInJlbSIsICJkZXAiKSkNCmBgYA0KDQpEaXN0cmlidXRpb24NCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YT0gZGZfbWVkYWxfY2xlYW4sIGFlcyh4PXJlbV9tZW1fbmVnX21vb2QpKSArIGdlb21faGlzdG9ncmFtKCkrZmFjZXRfZ3JpZChjb2xzPXZhcnMoY29uZGl0aW9uKSkNCmBgYA0KQ2VudHJlZCBEaXN0cmlidXRpb24gDQpgYGB7cn0NCmdncGxvdChkYXRhPSBkZl9tZWRhbF9jbGVhbiwgYWVzKHg9cmVtX21lbV9uZWdfbW9vZF9jKSkgKyBnZW9tX2hpc3RvZ3JhbSgpK2ZhY2V0X2dyaWQoY29scz12YXJzKGNvbmRpdGlvbikpDQpgYGANCg0KDQojIE1haW4gRWZmZWN0cyB7LnRhYnNldH0NCkEgc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uIGFuYWx5c2lzIHdhcyBkb25lIHRvIGxvb2sgYXQgdGhlIGRpZmZlcmVuY2VzIGluIHBvc2l0aXZlIGFuZCBuZWdhdGl2ZSBtb29kIHJhdGluZ3MgcGVyIGNvbmRpdGlvbi4NCg0KIyMgTGluZWFyIE1peGVkIE1vZGVscyBmb3IgUEEgYW5kIE5BDQpgYGB7cn0NCiNwb3NpdGl2ZSBtb29kIA0KcG9zaXRpdmVfbW9kZWwgPSBsbWVyKHBvc19tb29kIH4gY29uZGl0aW9uICsgKDF8c3ViamVjdGNvZGUpLCBkYXRhID0gZGZfbWVkYWxfY2xlYW4pDQoNCg0KI25lZ2F0aXZlIG1vb2QNCm5lZ2F0aXZlX21vZGVsID0gbG1lcihuZWdfbW9vZCB+IGNvbmRpdGlvbiArICgxfHN1YmplY3Rjb2RlKSwgZGF0YSA9IGRmX21lZGFsX2NsZWFuKQ0KDQoNCg0KYXNpc19vdXRwdXQodGFiX21vZGVsIChwb3NpdGl2ZV9tb2RlbCwgbmVnYXRpdmVfbW9kZWwsIA0KICAgICAgICAgICAgICAgICAgICAgIHNob3cuc2UgPSBULCBzaG93LmRmID0gVCwgc2hvdy5haWMgPSBULCB0cmFuc2Zvcm0gPSBOVUxMLCAgDQogICAgICAgICAgICAgICAgICAgICAgc2hvdy5zdGF0ID0gVCwgc2hvdy5zdGQgPSBULCANCiAgICAgICAgICAgICAgICAgICAgICB0aXRsZSA9ICdDb25kaXRpb24gRGlmZmVyZW5jZXMgTW9vZCBSYXRpbmcnLCBkdi5sYWJlbHMgPSBjKCdQQSBTY2FsZWQnLCAgJ05BIFNjYWxlZCcpICkka25pdHIpDQpgYGANCg0KIyMgUGxvdCB7LX0NCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCiNjcmVhdGUgYm94cGxvdCBmb3IgbmVnYXRpdmUgYW5kIHBvc2l0aXZlIGFmZmVjdCBmb3IgZWFjaCBncm91cCB3aXRoIHNpZ25pZmljYW5jZSBsZXZlbHMgDQpjb21iaW5lX2RhdGEgPSBkZl9tZWRhbF9jbGVhbiAlPiUNCiAgdGlkeXI6OnBpdm90X2xvbmdlcihjb2xzPWMocG9zX21vb2QsIG5lZ19tb29kKSwgbmFtZXNfdG8gPSAnbW9vZF90eXBlJywgdmFsdWVzX3RvID0gJ21vb2RfcmF0aW5nJykgJT4lIA0KICBkcGx5cjo6bXV0YXRlKG1vb2RfdHlwZSA9IGZhY3Rvcihtb29kX3R5cGUsIGxldmVscyA9IGMoJ3Bvc19tb29kJyAsICduZWdfbW9vZCcpKSkNCg0KIyBQbG90DQpsbV9wbG90ID0gZ2dwbG90KGNvbWJpbmVfZGF0YSwgYWVzKHg9Y29uZGl0aW9uLCB5ID0gbW9vZF9yYXRpbmcsIGZpbGw9IGNvbmRpdGlvbikpICsgDQogIGdlb21fYm94cGxvdCgpICsNCiAgbGFicyh4ID0nR3JvdXAnLCB5ID0nQWZmZWN0IChzY2FsZWQgdW5pdHMpJyApICsNCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBjKCdjb250cm9sJyA9ICdOZXZlciBEZXByZXNzZWQnLCAncmVtaXR0ZWQnID0gJ1JlbWl0dGVkJywgJ2RlcHJlc3NlZCcgPSAnRGVwcmVzc2VkJyApKSArDQogIGZhY2V0X3dyYXAoIH4gbW9vZF90eXBlLCBuY29sID0zLCBucm93ID0gMiwgbGFiZWxsZXIgID0gbGFiZWxsZXIobW9vZF90eXBlID0gYygncG9zX21vb2QnID0gJ1Bvc2l0aXZlIEFmZmVjdCcsICduZWdfbW9vZCcgID0gJ05lZ2F0aXZlIEFmZmVjdCcpKSkgKw0KICBnZW9tX3NpZ25pZihjb21wYXJpc29ucyA9IGxpc3QoYygnY29udHJvbCcsICdyZW1pdHRlZCcpLCBjKCdjb250cm9sJyAsICdkZXByZXNzZWQnKSwgYygncmVtaXR0ZWQnICwgJ2RlcHJlc3NlZCcgKSksIG1hcF9zaWduaWZfbGV2ZWwgPSBULCB5X3Bvc2l0aW9uID0gYygxNSwgMTMsIDExKSkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB3ZXNhbmRlcnNvbjo6d2VzX3BhbGV0dGUobj0zLCBuYW1lPSdHcmFuZEJ1ZGFwZXN0MicgKSkgICsNCiAgdGhlbWVfYXBhKCkgKyANCiAgZ3VpZGVzKGZpbGw9RikNCmdncGxvdGx5KGxtX3Bsb3QpDQpnZ3NhdmUoJ3Bsb3Rfc2ltcGxlX3JlZ3Jlc3Npb24ucGRmJywgZHBpID0gMzIwLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA4LCBwYXRoID0gImZpZ3VyZXMvIikNCmBgYA0KDQojIyBGb2xsb3ctVXAgey19DQpgYGB7cn0NCmVtbWVhbnM6OmVtbWVhbnMocG9zaXRpdmVfbW9kZWwsIHBhaXJ3aXNlIH4gY29uZGl0aW9uLCBwYmtydGVzdC5saW1pdCA9IDc4MDAsIGxtZXJUZXN0LmxpbWl0PTc4MDApDQplbW1lYW5zOjplbW1lYW5zKG5lZ2F0aXZlX21vZGVsLCBwYWlyd2lzZSB+IGNvbmRpdGlvbiwgcGJrcnRlc3QubGltaXQgPSA3ODAwLCBsbWVyVGVzdC5saW1pdD03ODAwKQ0KYGBgDQoNCg0KDQojIEh5cG90aGVzaXMgMTogSW5kZXBlbmRlbnQgTW9kZWxzICANCg0KSW4gdGhpcyBzZWN0aW9uIHdlIHRlc3QgdGhlIGZpcnN0IG1vZGVscyBmcm9tIGh5cG90aGVzaXMgMSBhcyBzdGF0ZWQgaW4gdGhlIHByZS1yZWdpc3RyYWl0b24uIFRoZXNlIGFuYWx5c2VzIGxvb2sgYXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHJlY2VudCBhbmQgcmVtb3RlIGVtb3Rpb25hbCBtZW1vcnkgZm9yIGJvdGggcG9zaXRpdmUgYW5kIG5lZ2F0aXZlIGFmZmVjdCwgd2hpbGUgYWxzbyBsb29raW5nIGF0IGdyb3VwIGRpZmZlcmVuY2VzIGluIHRoZXNlIHJlbGFpdG9uc2hpcHMgYmFzZWQgb24gZGVwcmVzc2lvbiBzdGF0dXMuIA0KDQpgYGB7cn0NCiMgc2V0IG1vZGVsIGZhbWlsaWVzDQptb2RlbF9mYW1pbGllcyA9IGMoJ2dhdXNzLWxpbmsnLCAiZ2F1c3MtbG9nIiwgJ2dhdXNzLWludicsICdHYW1tYS1saW5rJywgJ0dhbW1hLWxvZycpDQojIGRldGVjdCBjb3JlcyBmb3IgbGF0ZXINCm5jb3JlcyA9IGRldGVjdENvcmVzKCktMQ0KYGBgDQoNCiMjIFBvc2l0aXZlIEFmZmVjdCB7LSAudGFic2V0fQ0KDQpGaXJzdCB3ZSBydW4gdGhlIHBvc2l0aXZlIGFmZmVjdCBtb2RlbHMuIEZvciBlYWNoIG9mIHRoZSByZWNlbnQgYW5kIHJlbW90ZSBtb2RlbHMsIHdlIGNoZWNrIHRoZSBiZXN0IGZpdHRpbmcgbW9kZWwgYXMgc3RhdGVkIGluIHRoZSBwcmUtcmVnaXN0cmF0aW9uIGJhc2VkIG9uIHRoZSBBSUMgYW5kIHRoZSByZXNpZHVhbHMuIFdlIHRoZW4gY2hlY2sgd2hldGhlciBtZWRpYXRpb24gYW5hbHlzZXMgYXJlIHdhcnJhbnRlZCwgYW5kIHJ1biB0aG9zZS4gV2l0aGluIGVhY2ggdGFiIGJlbG93LCB3ZSBwcmVzZW50IHRoZSByZXN1bHRzIGFuZCBzdGVwcyB0YWtlbiwgYXMgd2VsbCBhcyBwb3N0LWhvYyBhbmFseXNlcyB0byBleGFtaW5lIHRoZSBkaXJlY3Rpb25hbGl0eSBvZiB0aGUgZWZmZWN0cy4gDQoNCiMjIyBSZWNlbnQgey0gfQ0KYGBge3J9DQojIE1vZGVsIGVxdWF0aW9uDQpoMV9wb3N0X3JlY2VudF9lcSA9ICJwb3NfbW9vZF9jcyB+IDEgKyBjb25kaXRpb24qcmVjX21lbV9wb3NfbW9vZF9jc19sYWcgKyBnZW5kZXIgKyBhZ2UgKyBlZHVjYXRpb24gKyAoMSArIHJlY19tZW1fcG9zX21vb2RfY3NfbGFnfHN1YmplY3Rjb2RlKSINCg0KIyBzZXQgY2x1c3RlcnMNCmNsID0gbWFrZUNsdXN0ZXIobmNvcmVzKQ0KcmVnaXN0ZXJEb1BhcmFsbGVsKGNsKQ0KDQojIHJ1biBwYXJhbGxlbA0KaDFfcG9zX3JlY2VudF9tb2RlbHMgPSBmb3JlYWNoKGZhbWlseSA9IG1vZGVsX2ZhbWlsaWVzLCAuY29tYmluZSA9ICdjJywgLnBhY2thZ2VzID0gYygnbG1lclRlc3QnKSwgLmVycm9yaGFuZGxpbmcgPSAicmVtb3ZlIikgJWRvcGFyJSB7DQogIGZpdF9hbGxfbW9kcyhoMV9wb3N0X3JlY2VudF9lcSwgZGZfbWVkYWxfY2xlYW4sIGZhbWlseSkgfQ0Kc3RvcENsdXN0ZXIoY2wpDQoNCiMgcHJpbnQgdGhlIG1vZGVscyBpbnRvIGEgc2luZ2xlIHRhYmxlDQphc2lzX291dHB1dCggdGFiX21vZGVsKGgxX3Bvc19yZWNlbnRfbW9kZWxzLCAgZHYubGFiZWxzID0gbmFtZXMoaDFfcG9zX3JlY2VudF9tb2RlbHMpLCANCiAgICAgICAgICAgICAgICAgICAgICAgc2hvdy5pY2MgPSBULCBzaG93LmFpYyA9IFQsIHRyYW5zZm9ybSA9IE5VTEwsIHNob3cuc2UgPSBULCBkaWdpdHMgPSAzKSRrbml0cikNCmBgYA0KDQpgYGB7cn0NCnN1bW1hcnkoaDFfcG9zX3JlY2VudF9tb2RlbHNbWzJdXSkNCnBsb3RfZGlhZ25vc3RpY3MoaDFfcG9zX3JlY2VudF9tb2RlbHMpDQpjYXI6OnZpZihoMV9wb3NfcmVjZW50X21vZGVsc1tbMl1dKSAjVmlmcyB3ZXJlIGluc3BlY3RlZCB3aXRob3V0IGludGVyYWN0aW9uIGFuZCBkZWVtZWQgT0sNCmBgYA0KDQojIyMjIyBGb2xsb3ctdXAgey19DQoNCkluIHRoZSBmb2xsb3ctdXAgd2UgbG9vayBhdCB0aGUgcGFpcndpc2UgZGlmZmVyZW5jZXMgaW4gdGhlIHNsb3BlcywgYW5kIHRoZSBpbmRpaXZ1ZHMNCmBgYHtyfQ0KZW1tZWFuczo6ZW10cmVuZHMoaDFfcG9zX3JlY2VudF9tb2RlbHNbWzJdXSwgcGFpcndpc2UgfiBjb25kaXRpb24sIHZhcj0ncmVjX21lbV9wb3NfbW9vZF9jc19sYWcnLCBsbWVyVGVzdC5saW1pdCA9IDM1MDAsIHBia3J0ZXN0LmxpbWl0ID0gMzUwMCApDQpgYGANCg0KYGBge3J9DQojY3JlYXRlIHNlcGFyYXRlIGRhdGFmcmFtZXMgDQpkZl9tZWRhbF9jbGVhbl9jb250cm9sID0gZGZfbWVkYWxfY2xlYW4gJT4lIGZpbHRlcihjb25kaXRpb24gPT0gJ2NvbnRyb2wnKQ0KZGZfbWVkYWxfY2xlYW5fcmVtaXR0ZWQgPSBkZl9tZWRhbF9jbGVhbiAlPiUgZmlsdGVyKGNvbmRpdGlvbiA9PSAncmVtaXR0ZWQnKQ0KZGZfbWVkYWxfY2xlYW5fZGVwcmVzc2VkID0gZGZfbWVkYWxfY2xlYW4gJT4lIGZpbHRlcihjb25kaXRpb24gPT0gJ2RlcHJlc3NlZCcpIA0KDQoNCm0xX3Bvc19yZWNfY29udHJvbCA8LSAgIGxtZXIocG9zX21vb2RfY3MgfiByZWNfbWVtX3Bvc19tb29kX2NzX2xhZyArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbiANCiAgICAgICAgICAgICAgICAgICAgICsgKDEgICsgIHJlY19tZW1fcG9zX21vb2RfY3NfbGFnfHN1YmplY3Rjb2RlKSwgDQogICAgICAgICAgICAgICAgICAgZGF0YT1kZl9tZWRhbF9jbGVhbl9jb250cm9sLA0KICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChjYWxjLmRlcml2cyA9IEYsIG9wdGltaXplcj0nYm9ieXFhJywgb3B0Q3RybD1saXN0KG1heGZ1bj0xZTYpKSkNCg0KbTFfcG9zX3JlY19yZW1pdHRlZCA8LSAgIGxtZXIocG9zX21vb2RfY3MgfiByZWNfbWVtX3Bvc19tb29kX2NzX2xhZyArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbiANCiAgICAgICAgICAgICAgICAgICAgICsgKDEgKyByZWNfbWVtX3Bvc19tb29kX2NzX2xhZ3xzdWJqZWN0Y29kZSksIA0KICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fcmVtaXR0ZWQsDQogICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKGNhbGMuZGVyaXZzID0gRiwgb3B0aW1pemVyPSdib2J5cWEnLCBvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNikpKQ0KDQptMV9wb3NfcmVjX2RlcHJlc3NlZCA8LSAgIGxtZXIocG9zX21vb2RfY3MgfiByZWNfbWVtX3Bvc19tb29kX2NzX2xhZyArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbiANCiAgICAgICAgICAgICAgICAgICAgICsgKDEgICsgcmVjX21lbV9wb3NfbW9vZF9jc19sYWd8c3ViamVjdGNvZGUpLCANCiAgICAgICAgICAgICAgICAgICBkYXRhPWRmX21lZGFsX2NsZWFuX2RlcHJlc3NlZCwNCiAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2woY2FsYy5kZXJpdnMgPSBGLCBvcHRpbWl6ZXI9J2JvYnlxYScsIG9wdEN0cmw9bGlzdChtYXhmdW49MWU2KSkpDQoNCmFzaXNfb3V0cHV0KHRhYl9tb2RlbChtMV9wb3NfcmVjX2NvbnRyb2wsIG0xX3Bvc19yZWNfcmVtaXR0ZWQsIG0xX3Bvc19yZWNfZGVwcmVzc2VkLCBzaG93LnNlID0gVCwgc2hvdy5haWMgPSBULCB0cmFuc2Zvcm0gPSBOVUxMLCBkdi5sYWJlbHMgPSBjKCdjb250cm9sJywgJ3JlbWl0dGVkJywgJ2RlcHJlc3NlZCcpKSRrbml0cikgDQpgYGANCg0KDQojIyMgUmVtb3RlIHstfQ0KYGBge3J9DQojIE1vZGVsIGVxdWF0aW9uDQpoMV9wb3NfcmVtb3RlX2VxID0gInBvc19tb29kX2NzIH4gMSArICBjb25kaXRpb24qcmVtX21lbV9wb3NfbW9vZF9jc19sYWcgKyBnZW5kZXIgKyBhZ2UgKyBlZHVjYXRpb24gKyAoMSAgKyByZW1fbWVtX3Bvc19tb29kX2NzX2xhZ3xzdWJqZWN0Y29kZSkiDQoNCiMgc2V0IGNsdXN0ZXJzDQpjbCA9IG1ha2VDbHVzdGVyKG5jb3JlcykNCnJlZ2lzdGVyRG9QYXJhbGxlbChjbCkNCg0KIyBydW4gcGFyYWxsZWwNCmgxX3Bvc19yZW1vdGVfbW9kZWxzID0gZm9yZWFjaChmYW1pbHkgPSBtb2RlbF9mYW1pbGllcywgLmNvbWJpbmUgPSAnYycsIC5wYWNrYWdlcyA9IGMoJ2xtZXJUZXN0JyksICAuZXJyb3JoYW5kbGluZyA9ICJyZW1vdmUiKSAlZG9wYXIlIHsNCiAgZml0X2FsbF9tb2RzKGgxX3Bvc19yZW1vdGVfZXEsIGRmX21lZGFsX2NsZWFuLCBmYW1pbHkpIH0NCnN0b3BDbHVzdGVyKGNsKQ0KDQojIHByaW50IHRoZSBtb2RlbHMgaW50byBhIHNpbmdsZSB0YWJsZQ0KYXNpc19vdXRwdXQoIHRhYl9tb2RlbChoMV9wb3NfcmVtb3RlX21vZGVscywgZHYubGFiZWxzID0gbmFtZXMoaDFfcG9zX3JlbW90ZV9tb2RlbHMpLCANCiAgICAgICAgICAgICAgICAgICAgICAgc2hvdy5pY2MgPSBULCBzaG93LmFpYyA9IFQsIHRyYW5zZm9ybSA9IE5VTEwsIHNob3cuc2UgPSBULCBkaWdpdHMgPSAzKSRrbml0cikNCmBgYA0KDQpgYGB7cn0NCnN1bW1hcnkoaDFfcG9zX3JlbW90ZV9tb2RlbHNbWzJdXSkNCnBsb3RfZGlhZ25vc3RpY3MoaDFfcG9zX3JlbW90ZV9tb2RlbHMpDQpjYXI6OnZpZihoMV9wb3NfcmVtb3RlX21vZGVsc1tbMl1dKSAjVklGcyB3aXRob3V0IGludGVyYWN0aW9ucyB3ZXJlIGZpbmUNCmBgYA0KDQoNCiMjIyMjIEZvbGxvdy11cCB7LX0NCmBgYHtyfQ0KZW1tZWFuczo6ZW10cmVuZHMoaDFfcG9zX3JlbW90ZV9tb2RlbHNbWzRdXSwgcGFpcndpc2UgfiBjb25kaXRpb24sIHZhcj0ncmVtX21lbV9wb3NfbW9vZF9jc19sYWcnICkNCg0KYGBgDQoNCg0KYGBge3J9DQoNCm0xX3Bvc19yZW1fY29udHJvbCA8LSBsbWVyKHBvc19tb29kX2NzIH4gMSArIHJlbV9tZW1fcG9zX21vb2RfY3NfbGFnICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgKDEgICsgcmVtX21lbV9wb3NfbW9vZF9jc19sYWd8c3ViamVjdGNvZGUpLCANCiAgICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fY29udHJvbCwNCiAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKGNhbGMuZGVyaXZzID0gRiwgb3B0aW1pemVyPSdib2J5cWEnLCBvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNikpKQ0KDQptMV9wb3NfcmVtX3JlbWl0dGVkIDwtIGxtZXIocG9zX21vb2RfY3MgfiAxICsgcmVtX21lbV9wb3NfbW9vZF9jc19sYWcgKyBnZW5kZXIgKyBhZ2UgKyBlZHVjYXRpb24gKyAoMSAgKyByZW1fbWVtX3Bvc19tb29kX2NzX2xhZ3xzdWJqZWN0Y29kZSksIA0KICAgICAgICAgICAgICAgICAgICAgZGF0YT1kZl9tZWRhbF9jbGVhbl9yZW1pdHRlZCwNCiAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChjYWxjLmRlcml2cyA9IEYsIG9wdGltaXplcj0nYm9ieXFhJywgb3B0Q3RybD1saXN0KG1heGZ1bj0xZTYpKSkNCg0KbTFfcG9zX3JlbV9kZXByZXNzZWQgPC0gbG1lcihwb3NfbW9vZF9jcyB+IDEgKyByZW1fbWVtX3Bvc19tb29kX2NzX2xhZyArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbiArICgxICArIHJlbV9tZW1fcG9zX21vb2RfY3NfbGFnfHN1YmplY3Rjb2RlKSwgDQogICAgICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fZGVwcmVzc2VkLA0KICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2woY2FsYy5kZXJpdnMgPSBGLCBvcHRpbWl6ZXI9J2JvYnlxYScsIG9wdEN0cmw9bGlzdChtYXhmdW49MWU2KSkpDQoNCmFzaXNfb3V0cHV0KHRhYl9tb2RlbChtMV9wb3NfcmVtX2NvbnRyb2wsIG0xX3Bvc19yZW1fcmVtaXR0ZWQsIG0xX3Bvc19yZW1fZGVwcmVzc2VkLCBzaG93LnNlID0gVCwgc2hvdy5haWMgPSBULCB0cmFuc2Zvcm0gPSBOVUxMLCBkdi5sYWJlbHMgPSBjKCdjb250cm9sJywgJ3JlbWl0dGVkJywgJ2RlcHJlc3NlZCcpKSRrbml0cikgDQoNCmBgYA0KDQoNCg0KDQojIyBOZWdhdGl2ZSBBZmZlY3Qgey0gLnRhYnNldH0NCg0KV2UgbmV4dCBydW4gdGhlIG5lZ2F0aXZlIGFmZmVjdCBtb2RlbHMuIEZvciBlYWNoIG9mIHRoZSByZWNlbnQgYW5kIHJlbW90ZSBtb2RlbHMsIHdlIGNoZWNrIHRoZSBiZXN0IGZpdHRpbmcgbW9kZWwgYXMgc3RhdGVkIGluIHRoZSBwcmUtcmVnaXN0cmF0aW9uIGJhc2VkIG9uIHRoZSBBSUMgYW5kIHRoZSByZXNpZHVhbHMuIFdlIHRoZW4gY2hlY2sgd2hldGhlciBtZWRpYXRpb24gYW5hbHlzZXMgYXJlIHdhcnJhbnRlZCwgYW5kIHJ1biB0aG9zZS4gV2l0aGluIGVhY2ggdGFiIGJlbG93LCB3ZSBwcmVzZW50IHRoZSByZXN1bHRzIGFuZCBzdGVwcyB0YWtlbiwgYXMgd2VsbCBhcyBwb3N0LWhvYyBhbmFseXNlcyB0byBleGFtaW5lIHRoZSBkaXJlY3Rpb25hbGl0eSBvZiB0aGUgZWZmZWN0cw0KDQojIyMgUmVjZW50IHstfQ0KYGBge3J9DQojIE1vZGVsIGVxdWF0aW9uDQpoMV9uZWdfcmVjZW50X2VxID0gIm5lZ19tb29kX2NzIH4gY29uZGl0aW9uKnJlY19tZW1fbmVnX21vb2RfY3NfbGFnICArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbiArICgxICsgcmVjX21lbV9uZWdfbW9vZF9jc19sYWcgfCBzdWJqZWN0Y29kZSkiDQojIHNldCBjbHVzdGVycw0KY2wgPSBtYWtlQ2x1c3RlcihuY29yZXMpDQpyZWdpc3RlckRvUGFyYWxsZWwoY2wpDQoNCiMgcnVuIHBhcmFsbGVsDQpoMV9uZWdfcmVjZW50X21vZGVscyA9IGZvcmVhY2goZmFtaWx5ID0gbW9kZWxfZmFtaWxpZXMsIC5jb21iaW5lID0gJ2MnLCAucGFja2FnZXMgPSBjKCdsbWVyVGVzdCcpLCAuZXJyb3JoYW5kbGluZyA9ICdyZW1vdmUnKSAlZG9wYXIlIHsNCiAgZml0X2FsbF9tb2RzKGgxX25lZ19yZWNlbnRfZXEsIGRmX21lZGFsX2NsZWFuLCBmYW1pbHkpIH0NCnN0b3BDbHVzdGVyKGNsKQ0KDQojIHByaW50IHRoZSBtb2RlbHMgaW50byBhIHNpbmdsZSB0YWJsZQ0KYXNpc19vdXRwdXQoIHRhYl9tb2RlbChoMV9uZWdfcmVjZW50X21vZGVscywgIGR2LmxhYmVscyA9IG5hbWVzKGgxX25lZ19yZWNlbnRfbW9kZWxzKSwgDQogICAgICAgICAgICAgICAgICAgICAgIHNob3cuaWNjID0gVCwgc2hvdy5haWMgPSBULCB0cmFuc2Zvcm0gPSBOVUxMLCBzaG93LnNlID0gVCwgZGlnaXRzID0gMykka25pdHIpDQoNCmBgYA0KDQoNCmBgYHtyfQ0Kc3VtbWFyeShoMV9uZWdfcmVjZW50X21vZGVsc1tbNF1dKQ0KcGxvdF9kaWFnbm9zdGljcyhoMV9uZWdfcmVjZW50X21vZGVscykNCmNhcjo6dmlmKGgxX25lZ19yZWNlbnRfbW9kZWxzW1s0XV0pDQpgYGANCg0KDQoNCiMjIyMgRm9sbG93LXVwIHstfQ0KYGBge3J9DQplbW1lYW5zOjplbXRyZW5kcyhoMV9uZWdfcmVjZW50X21vZGVsc1tbNF1dLCBwYWlyd2lzZSB+IGNvbmRpdGlvbiwgdmFyPSdyZWNfbWVtX25lZ19tb29kX2NzX2xhZycgKQ0KDQplbW1lYW5zOjplbW1lYW5zKGgxX25lZ19yZWNlbnRfbW9kZWxzW1s0XV0sIGlkZW50aXR5IH4gcmVjX21lbV9uZWdfbW9vZF9jc19sYWcgfCBjb25kaXRpb24gKQ0KYGBgDQoNCg0KYGBge3J9DQoNCm0xX25lZ19yZWNfY29udHJvbCA8LSBnbG1lcihuZWdfbW9vZF9jcyB+IDEgKyByZWNfbWVtX25lZ19tb29kX2NzX2xhZyArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbiArICgwICArIHJlY19tZW1fbmVnX21vb2RfY3NfbGFnfHN1YmplY3Rjb2RlKSwgDQogICAgICAgICAgICAgICAgICAgZGF0YT1kZl9tZWRhbF9jbGVhbl9jb250cm9sLA0KICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IEdhbW1hKGxpbms9aWRlbnRpdHkpLA0KICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBnbG1lckNvbnRyb2woY2FsYy5kZXJpdnMgPSBGLCBvcHRpbWl6ZXI9J2JvYnlxYScsIG9wdEN0cmw9bGlzdChtYXhmdW49MWU2KSkpDQoNCm0xX25lZ19yZWNfcmVtaXR0ZWQgPC1nbG1lcihuZWdfbW9vZF9jcyB+IDEgKyByZWNfbWVtX25lZ19tb29kX2NzX2xhZyArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbiArICgwICArIHJlY19tZW1fbmVnX21vb2RfY3NfbGFnfHN1YmplY3Rjb2RlKSwgDQogICAgICAgICAgICAgICAgICAgZGF0YT1kZl9tZWRhbF9jbGVhbl9yZW1pdHRlZCwNCiAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBHYW1tYShsaW5rPWlkZW50aXR5KSwNCiAgICAgICAgICAgICAgICAgICBjb250cm9sID0gZ2xtZXJDb250cm9sKGNhbGMuZGVyaXZzID0gRiwgb3B0aW1pemVyPSdib2J5cWEnLCBvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNikpKQ0KDQptMV9uZWdfcmVjX2RlcHJlc3NlZCA8LWdsbWVyKG5lZ19tb29kX2NzIH4gMSArIHJlY19tZW1fbmVnX21vb2RfY3NfbGFnICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgKDAgICsgcmVjX21lbV9uZWdfbW9vZF9jc19sYWd8c3ViamVjdGNvZGUpLCANCiAgICAgICAgICAgICAgICAgICBkYXRhPWRmX21lZGFsX2NsZWFuX2RlcHJlc3NlZCwNCiAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBHYW1tYShsaW5rPWlkZW50aXR5KSwNCiAgICAgICAgICAgICAgICAgICBjb250cm9sID0gZ2xtZXJDb250cm9sKGNhbGMuZGVyaXZzID0gRiwgb3B0aW1pemVyPSdib2J5cWEnLCBvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNikpKQ0KDQphc2lzX291dHB1dCh0YWJfbW9kZWwobTFfbmVnX3JlY19jb250cm9sLCBtMV9uZWdfcmVjX3JlbWl0dGVkLCBtMV9uZWdfcmVjX2RlcHJlc3NlZCwgc2hvdy5zZSA9IFQsIHNob3cuYWljID0gVCwgdHJhbnNmb3JtID0gTlVMTCwgZHYubGFiZWxzID0gYygnY29udHJvbCcsICdyZW1pdHRlZCcsICdkZXByZXNzZWQnKSkka25pdHIpIA0KYGBgDQoNCiMjIyBSZW1vdGUgey19DQpgYGB7cn0NCiMgTW9kZWwgZXF1YXRpb24NCmgxX25lZ19yZW1vdGVfZXEgPSAibmVnX21vb2RfY3MgfiBjb25kaXRpb24qcmVtX21lbV9uZWdfbW9vZF9jc19sYWcgICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgKDAgICsgcmVtX21lbV9uZWdfbW9vZF9jc19sYWd8c3ViamVjdGNvZGUpIg0KDQojIHNldCBjbHVzdGVycw0KY2wgPSBtYWtlQ2x1c3RlcihuY29yZXMpDQpyZWdpc3RlckRvUGFyYWxsZWwoY2wpDQoNCiMgcnVuIHBhcmFsbGVsDQpoMV9uZWdfcmVtb3RlX21vZGVscyA9IGZvcmVhY2goZmFtaWx5ID0gbW9kZWxfZmFtaWxpZXMsIC5jb21iaW5lID0gJ2MnLCAucGFja2FnZXMgPSBjKCdsbWVyVGVzdCcpLCAgLmVycm9yaGFuZGxpbmcgPSAicmVtb3ZlIikgJWRvcGFyJSB7DQogIGZpdF9hbGxfbW9kcyhoMV9uZWdfcmVtb3RlX2VxLCBkZl9tZWRhbF9jbGVhbiwgZmFtaWx5KSB9DQpzdG9wQ2x1c3RlcihjbCkNCg0KIyBwcmludCB0aGUgbW9kZWxzIGludG8gYSBzaW5nbGUgdGFibGUNCmFzaXNfb3V0cHV0KCB0YWJfbW9kZWwoaDFfbmVnX3JlbW90ZV9tb2RlbHMsICAgZHYubGFiZWxzID0gbmFtZXMoaDFfbmVnX3JlbW90ZV9tb2RlbHMpLCANCiAgICAgICAgICAgICAgICAgICAgICAgc2hvdy5pY2MgPSBULCBzaG93LmFpYyA9IFQsIHRyYW5zZm9ybSA9IE5VTEwsIHNob3cuc2UgPSBULCBkaWdpdHMgPSAzKSRrbml0cikNCg0KYGBgDQoNCg0KYGBge3J9DQpzdW1tYXJ5KGgxX25lZ19yZW1vdGVfbW9kZWxzW1syXV0pDQpwbG90X2RpYWdub3N0aWNzKGgxX25lZ19yZW1vdGVfbW9kZWxzKQ0KY2FyOjp2aWYoaDFfbmVnX3JlbW90ZV9tb2RlbHNbWzJdXSkNCmBgYA0KDQoNCiMjIyMgRm9sbG93LXVwIHstfQ0KYGBge3J9DQplbW1lYW5zOjplbXRyZW5kcyhoMV9uZWdfcmVtb3RlX21vZGVsc1tbMl1dLCBwYWlyd2lzZSB+IGNvbmRpdGlvbiwgdmFyPSdyZW1fbWVtX25lZ19tb29kX2NzX2xhZycgKQ0KDQpgYGANCg0KYGBge3J9DQoNCm0xX25lZ19yZW1fY29udHJvbCA8LSAgZ2xtZXIobmVnX21vb2RfY3MgfiAxICsgcmVtX21lbV9uZWdfbW9vZF9jc19sYWcgKyBnZW5kZXIgKyBhZ2UgKyBlZHVjYXRpb24gKyAoMCAgKyByZW1fbWVtX25lZ19tb29kX2NzX2xhZ3xzdWJqZWN0Y29kZSksIA0KICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fY29udHJvbCwNCiAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBHYW1tYShsaW5rPWlkZW50aXR5KSwNCiAgICAgICAgICAgICAgICAgICBjb250cm9sID0gZ2xtZXJDb250cm9sKGNhbGMuZGVyaXZzID0gRiwgb3B0aW1pemVyPSdib2J5cWEnLCBvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNikpKQ0KDQptMV9uZWdfcmVtX3JlbWl0dGVkIDwtIGdsbWVyKG5lZ19tb29kX2NzIH4gMSArIHJlbV9tZW1fbmVnX21vb2RfY3NfbGFnICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgKDAgICsgcmVtX21lbV9uZWdfbW9vZF9jc19sYWd8c3ViamVjdGNvZGUpLA0KICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fcmVtaXR0ZWQsDQogICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gR2FtbWEobGluaz1pZGVudGl0eSksDQogICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGdsbWVyQ29udHJvbChjYWxjLmRlcml2cyA9IEYsIG9wdGltaXplcj0nYm9ieXFhJywgb3B0Q3RybD1saXN0KG1heGZ1bj0xZTYpKSkNCg0KbTFfbmVnX3JlbV9kZXByZXNzZWQgPC0gIGdsbWVyKG5lZ19tb29kX2NzIH4gMSArIHJlbV9tZW1fbmVnX21vb2RfY3NfbGFnICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgKDAgICsgcmVtX21lbV9uZWdfbW9vZF9jc19sYWd8c3ViamVjdGNvZGUpLA0KICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fZGVwcmVzc2VkLA0KICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IEdhbW1hKGxpbms9aWRlbnRpdHkpLA0KICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBnbG1lckNvbnRyb2woY2FsYy5kZXJpdnMgPSBGLCBvcHRpbWl6ZXI9J2JvYnlxYScsIG9wdEN0cmw9bGlzdChtYXhmdW49MWU2KSkpDQoNCmFzaXNfb3V0cHV0KHRhYl9tb2RlbChtMV9uZWdfcmVtX2NvbnRyb2wsIG0xX25lZ19yZW1fcmVtaXR0ZWQsIG0xX25lZ19yZW1fZGVwcmVzc2VkLCBzaG93LnNlID0gVCwgc2hvdy5haWMgPSBULCB0cmFuc2Zvcm0gPSBOVUxMLCBkdi5sYWJlbHMgPSBjKCdjb250cm9sJywgJ3JlbWl0dGVkJywgJ2RlcHJlc3NlZCcpKSRrbml0cikgDQpgYGANCg0KDQoNCiMgSHlwb3RoZXNpcyAyOiBDdXJyZW50IEFmZmVjdCBNb2RlcmF0aW9uIA0KDQpGb3IgSDIsIHdlIHdhbnQgdG8gc2VlIHdoZXRoZXIgY3VycmVudCBhZmZlY3RpdmUgc3RhdGVzIG1vZGVyYXRlIHRoZSBhYmlsaXR5IHRvIHJlY2FsbCBwcmV2aW91cyBhZmZlY3RpdmUgc3RhdGVzLiBUaGF0IGlzLCBkbyBjdXJyZW50IG5lZ2F0aXZlIGFmZmVjdCBmZWVsaW5ncyBtb2RlcmF0ZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gYWZmZWN0IGFuZCByZWNhbGw/IA0KDQpgYGB7cn0NCiNjcmVhdGUgc2VwYXJhdGUgZGF0YWZyYW1lcyBmb3IgZWFjaCBncm91cA0KZGZfbWVkYWxfY2xlYW5fY29udHJvbCA9IGRmX21lZGFsX2NsZWFuICU+JSBmaWx0ZXIoY29uZGl0aW9uPT0nY29udHJvbCcpDQpkZl9tZWRhbF9jbGVhbl9yZW1pdHRlZCA9IGRmX21lZGFsX2NsZWFuICU+JSBmaWx0ZXIoY29uZGl0aW9uPT0ncmVtaXR0ZWQnKQ0KZGZfbWVkYWxfY2xlYW5fZGVwcmVzc2VkID0gZGZfbWVkYWxfY2xlYW4gJT4lIGZpbHRlcihjb25kaXRpb249PSdkZXByZXNzZWQnKQ0KDQojY3JlYXRlIGEgbmV3IGRhdGFmcmFtZSBmb3IgdGhlIHJlbW90ZSB2YXJpYWJsZXMsIHdoZXJlIHRoZSBwYXJ0aWNpcGFudHMgd2l0aCB0aGUgc2luZ3VsYXIgZGF0YXBvaW50cyBhcmUgcmVtb3ZlZCANCmRmX21lZGFsX2NsZWFuX3JlbW90ZSA9IGRmX21lZGFsX2NsZWFuICU+JSBmaWx0ZXIgKCEoc3ViamVjdGNvZGUgPT0gODIyIHwgc3ViamVjdGNvZGUgPT0gOTA2IHwgc3ViamVjdGNvZGUgPT0gNzE3KSkNCg0KI2NyZWF0ZSBzZXBhcmF0ZSBkYXRhZnJhbWVzIHBlciBjb25kaXRpb24gDQpkZl9tZWRhbF9jbGVhbl9yZW1vdGVfY29udHJvbCA9IGRmX21lZGFsX2NsZWFuX3JlbW90ZSAlPiUgZmlsdGVyKGNvbmRpdGlvbj09J2NvbnRyb2wnKQ0KZGZfbWVkYWxfY2xlYW5fcmVtb3RlX3JlbWl0dGVkID0gZGZfbWVkYWxfY2xlYW5fcmVtb3RlICU+JSBmaWx0ZXIoY29uZGl0aW9uPT0ncmVtaXR0ZWQnKQ0KZGZfbWVkYWxfY2xlYW5fcmVtb3RlX2RlcHJlc3NlZCA9IGRmX21lZGFsX2NsZWFuX3JlbW90ZSAlPiUgZmlsdGVyKGNvbmRpdGlvbj09J2RlcHJlc3NlZCcpDQpgYGANCg0KIyMgUG9zaXRpdmUgQWZmZWN0IHstIC50YWJzZXR9DQoNCiMjIyBSZWNlbnQgey19DQpBbiBsbWVyIG1vZGVsIHdhcyBmaXR0ZWQgd2l0aCBnYXVzc2lhbiBpZGVudGl0eSwgbG9nICYgaW52ZXJzZSBhcyB3ZWxsIGFzIEdhbW1hIGxvZywgaW52ZXJzZSwgYW5kIGlkZW50aXR5LiBUaGUgbW9kZWxzLCBob3dldmVyLCB3ZXJlIG5vdCBhIGdvb2QgZml0IGFuZCB0aGUgZ2F1c3NpYW4gaWRlbnRpdHkgbW9kZWwgY29wZWQgd2l0aCBzaW5ndWxhcml0eS4gSGVuY2UsIGEgbm9ybWFsIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIHdhcyBmaXR0ZWQuIA0KYGBge3IgZmlnLmhlaWdodD0yMCwgZmlnLndpZHRoPTE1fQ0KaDJfcG9zX3JlY2VudF9lcSA9ICJwb3NfbW9vZF9jcyB+IGNvbmRpdGlvbipyZWNfbWVtX3Bvc19tb29kX2NzX2xhZypwb3NfbW9vZF9jc19sYWdfcmVjICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgKDEgKyByZWNfbWVtX3Bvc19tb29kX2NzX2xhZyArIHBvc19tb29kX2NzX2xhZ19yZWN8c3ViamVjdGNvZGUpIg0KDQojIHNldCBjbHVzdGVycw0KY2wgPSBtYWtlQ2x1c3RlcihuY29yZXMpDQpyZWdpc3RlckRvUGFyYWxsZWwoY2wpDQoNCiMgcnVuIHBhcmFsbGVsDQpoMl9wb3NfcmVjZW50X21vZGVscyA9IGZvcmVhY2goZmFtaWx5ID0gbW9kZWxfZmFtaWxpZXMsIC5jb21iaW5lID0gJ2MnLCAucGFja2FnZXMgPSBjKCdsbWVyVGVzdCcpLCAgLmVycm9yaGFuZGxpbmcgPSAicmVtb3ZlIikgJWRvcGFyJSB7DQogIGZpdF9hbGxfbW9kcyhoMl9wb3NfcmVjZW50X2VxLCBkZl9tZWRhbF9jbGVhbiwgZmFtaWx5KSB9DQpzdG9wQ2x1c3RlcihjbCkNCg0KIyBwcmludCB0aGUgbW9kZWxzIGludG8gYSBzaW5nbGUgdGFibGUNCmFzaXNfb3V0cHV0KCB0YWJfbW9kZWwoaDJfcG9zX3JlY2VudF9tb2RlbHMsICBkdi5sYWJlbHMgPSBuYW1lcyhoMl9wb3NfcmVjZW50X21vZGVscyksIA0KICAgICAgICAgICAgICAgICAgICAgICBzaG93LmljYyA9IFQsIHNob3cuYWljID0gVCwgdHJhbnNmb3JtID0gTlVMTCwgc2hvdy5zZSA9IFQsIGRpZ2l0cyA9IDMpJGtuaXRyKQ0KDQoNCmBgYA0KDQpEdWUgdG8gc2luZ3VsYXJpdHkgdGhpcyB3YXMgZGV0ZXJtaW5lZCB0byBiZSB0aGUgYmVzdCBmaXQgZm9yIHRoZSBtb2RkZWwNCg0KYGBge3J9DQpzdW1tYXJ5KGgyX3Bvc19yZWNlbnRfbW9kZWxzW1syXV0pDQpwbG90X2RpYWdub3N0aWNzKGgyX3Bvc19yZWNlbnRfbW9kZWxzKQ0KY2FyOjp2aWYoaDJfcG9zX3JlY2VudF9tb2RlbHNbWzJdXSkNCmBgYA0KDQoNCg0KIyMjIyBGb2xsb3ctdXAgey19DQpgYGB7cn0NCm0yX3Bvc19yZWNfY29udHJvbCA8LSBsbShwb3NfbW9vZF9jcyB+IDEgKyByZWNfbWVtX3Bvc19tb29kX2NzX2xhZypwb3NfbW9vZF9jc19sYWdfcmVjICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uLA0KICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fY29udHJvbCkNCg0KbTJfcG9zX3JlY19yZW1pdHRlZCA8LSBsbShwb3NfbW9vZF9jcyB+IDEgKyByZWNfbWVtX3Bvc19tb29kX2NzX2xhZypwb3NfbW9vZF9jc19sYWdfcmVjICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uLA0KICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fcmVtaXR0ZWQpDQoNCm0yX3Bvc19yZWNfZGVwcmVzc2VkIDwtICBsbShwb3NfbW9vZF9jcyB+IDEgKyByZWNfbWVtX3Bvc19tb29kX2NzX2xhZypwb3NfbW9vZF9jc19sYWdfcmVjICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uLA0KICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fZGVwcmVzc2VkKQ0KDQphc2lzX291dHB1dCh0YWJfbW9kZWwobTJfcG9zX3JlY19jb250cm9sLCBtMl9wb3NfcmVjX3JlbWl0dGVkLCBtMl9wb3NfcmVjX2RlcHJlc3NlZCwgc2hvdy5zZSA9IFQsIHNob3cuYWljID0gVCwgdHJhbnNmb3JtID0gTlVMTCwgZHYubGFiZWxzID0gYygnY29udHJvbCcsICdyZW1pdHRlZCcsICdkZXByZXNzZWQnKSkka25pdHIpDQpgYGANCg0KDQojIyMgUmVtb3RlIHstIC50YWJzZXR9DQoNCkFuIGxtZXIgbW9kZWwgd2FzIGZpdHRlZCB3aXRoIGdhdXNzaWFuIGlkZW50aXR5LCBsb2cgJiBpbnZlcnNlIGFzIHdlbGwgYXMgR2FtbWEgbG9nLCBpbnZlcnNlLCBhbmQgaWRlbnRpdHkuIFRoZSBtb2RlbHMsIGhvd2V2ZXIsIHdlcmUgbm90IGEgZ29vZCBmaXQgYW5kIHRoZSBnYXVzc2lhbiBpZGVudGl0eSBtb2RlbCBjb3BlZCB3aXRoIHNpbmd1bGFyaXR5LiBIZW5jZSwgYSBub3JtYWwgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgd2FzIGZpdHRlZC4gDQpgYGB7cn0NCmgyX3Bvc19yZW1vdGVfZXEgPSAicG9zX21vb2RfY3MgfiBjb25kaXRpb24qcmVtX21lbV9wb3NfbW9vZF9jc19sYWcqcG9zX21vb2RfY3NfbGFnX3JlbSArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbiArICgxIHwgc3ViamVjdGNvZGUpIg0KDQojIHNldCBjbHVzdGVycw0KY2wgPSBtYWtlQ2x1c3RlcihuY29yZXMpDQpyZWdpc3RlckRvUGFyYWxsZWwoY2wpDQoNCiMgcnVuIHBhcmFsbGVsDQpoMl9wb3NfcmVtb3RlX21vZGVscyA9IGZvcmVhY2goZmFtaWx5ID0gbW9kZWxfZmFtaWxpZXMsIC5jb21iaW5lID0gJ2MnLCAucGFja2FnZXMgPSBjKCdsbWVyVGVzdCcpLCAgLmVycm9yaGFuZGxpbmcgPSAicmVtb3ZlIikgJWRvcGFyJSB7DQogIGZpdF9hbGxfbW9kcyhoMl9wb3NfcmVtb3RlX2VxLCBkZl9tZWRhbF9jbGVhbiwgZmFtaWx5KSB9DQpzdG9wQ2x1c3RlcihjbCkNCg0KIyBwcmludCB0aGUgbW9kZWxzIGludG8gYSBzaW5nbGUgdGFibGUNCmFzaXNfb3V0cHV0KCB0YWJfbW9kZWwoaDJfcG9zX3JlbW90ZV9tb2RlbHMsICBkdi5sYWJlbHMgPSBuYW1lcyhoMl9wb3NfcmVtb3RlX21vZGVscyksIA0KICAgICAgICAgICAgICAgICAgICAgICBzaG93LmljYyA9IFQsIHNob3cuYWljID0gVCwgdHJhbnNmb3JtID0gTlVMTCwgc2hvdy5zZSA9IFQsIGRpZ2l0cyA9IDMpJGtuaXRyKQ0KDQoNCmBgYA0KDQoNCkR1ZSB0byBzaW5ndWxhcml0eSBhIHJlZ3VsYXIgbGluZWFyIG1vZGVsIHdhcyBmaXR0ZWQuDQpgYGB7cn0NCnN1bW1hcnkoaDJfcG9zX3JlbW90ZV9tb2RlbHNbWzJdXSkNCnBsb3RfZGlhZ25vc3RpY3MoaDJfcG9zX3JlbW90ZV9tb2RlbHMpDQpjYXI6OnZpZihoMl9wb3NfcmVtb3RlX21vZGVsc1tbMl1dKQ0KDQpgYGANCg0KDQojIyMjIEZvbGxvdy11cCB7LX0NCmBgYHtyfQ0KDQptMl9wb3NfcmVtX2NvbnRyb2wgPC0gbG0ocG9zX21vb2RfY3MgfiByZW1fbWVtX3Bvc19tb29kX2NzX2xhZypwb3NfbW9vZF9jc19sYWdfcmVtICArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbiwgDQogICAgICAgICAgICAgICAgICAgZGF0YT1kZl9tZWRhbF9jbGVhbl9yZW1vdGVfY29udHJvbCkNCg0KbTJfcG9zX3JlbV9yZW1pdHRlZCA8LSBsbShwb3NfbW9vZF9jcyB+IHJlbV9tZW1fcG9zX21vb2RfY3NfbGFnKnBvc19tb29kX2NzX2xhZ19yZW0gICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uLCAgDQogICAgICAgICAgICAgICAgICAgZGF0YT1kZl9tZWRhbF9jbGVhbl9yZW1vdGVfcmVtaXR0ZWQpDQoNCm0yX3Bvc19yZW1fZGVwcmVzc2VkIDwtICBsbShwb3NfbW9vZF9jcyB+IHJlbV9tZW1fcG9zX21vb2RfY3NfbGFnKnBvc19tb29kX2NzX2xhZ19yZW0gICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uLCANCiAgICAgICAgICAgICAgICAgICBkYXRhPWRmX21lZGFsX2NsZWFuX3JlbW90ZV9kZXByZXNzZWQpDQoNCmFzaXNfb3V0cHV0KHRhYl9tb2RlbChtMl9wb3NfcmVtX2NvbnRyb2wsIG0yX3Bvc19yZW1fcmVtaXR0ZWQsIG0yX3Bvc19yZW1fZGVwcmVzc2VkLCBzaG93LnNlID0gVCwgc2hvdy5haWMgPSBULCB0cmFuc2Zvcm0gPSBOVUxMLCBkdi5sYWJlbHMgPSBjKCdjb250cm9sJywgJ3JlbWl0dGVkJywgJ2RlcHJlc3NlZCcpKSRrbml0cikgDQpgYGANCg0KDQoNCiMjIE5lZ2F0aXZlIEFmZmVjdCB7LSAudGFic2V0fQ0KDQojIyMgIFJlY2VudCB7LX0NCmBgYHtyfQ0KaDJfbmVnX3JlY2VudF9lcSA9ICJuZWdfbW9vZF9jcyB+IGNvbmRpdGlvbipyZWNfbWVtX25lZ19tb29kX2NzX2xhZypuZWdfbW9vZF9jc19sYWdfcmVjICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgKDEgKyByZWNfbWVtX25lZ19tb29kX2NzX2xhZyArIG5lZ19tb29kX2NzX2xhZ19yZWN8c3ViamVjdGNvZGUpIg0KDQojIHNldCBjbHVzdGVycw0KY2wgPSBtYWtlQ2x1c3RlcihuY29yZXMpDQpyZWdpc3RlckRvUGFyYWxsZWwoY2wpDQoNCiMgcnVuIHBhcmFsbGVsDQpoMl9uZWdfcmVjZW50X21vZGVscyA9IGZvcmVhY2goZmFtaWx5ID0gbW9kZWxfZmFtaWxpZXMsIC5jb21iaW5lID0gJ2MnLCAucGFja2FnZXMgPSBjKCdsbWVyVGVzdCcpLCAgLmVycm9yaGFuZGxpbmcgPSAicmVtb3ZlIikgJWRvcGFyJSB7DQogIGZpdF9hbGxfbW9kcyhoMl9uZWdfcmVjZW50X2VxLCBkZl9tZWRhbF9jbGVhbiwgZmFtaWx5KSB9DQpzdG9wQ2x1c3RlcihjbCkNCg0KIyBwcmludCB0aGUgbW9kZWxzIGludG8gYSBzaW5nbGUgdGFibGUNCmFzaXNfb3V0cHV0KCB0YWJfbW9kZWwoaDJfbmVnX3JlY2VudF9tb2RlbHMsIGR2LmxhYmVscyA9IG5hbWVzKGgyX25lZ19yZWNlbnRfbW9kZWxzKSwgDQogICAgICAgICAgICAgICAgICAgICAgIHNob3cuaWNjID0gVCwgc2hvdy5haWMgPSBULCB0cmFuc2Zvcm0gPSBOVUxMLCBzaG93LnNlID0gVCwgZGlnaXRzID0gMykka25pdHIpDQoNCmBgYA0KDQpDaGVjayBGaW5hbCBNb2RlbA0KYGBge3IgfQ0Kc3VtbWFyeShoMl9uZWdfcmVjZW50X21vZGVsc1tbNF1dKQ0KcGxvdF9kaWFnbm9zdGljcyhoMl9uZWdfcmVjZW50X21vZGVscykgDQpjYXI6OnZpZihoMl9uZWdfcmVjZW50X21vZGVsc1tbNF1dKQ0KDQpgYGANCg0KDQoNCg0KIyMjIyBGb2xsb3ctdXAgey19DQpgYGB7cn0NCg0KbTJfbmVnX3JlY19jb250cm9sIDwtIGdsbWVyKG5lZ19tb29kX2NzIH4gcmVjX21lbV9uZWdfbW9vZF9jc19sYWcqbmVnX21vb2RfY3NfbGFnX3JlYyArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSAgKyByZWNfbWVtX25lZ19tb29kX2NzX2xhZyB8IHN1YmplY3Rjb2RlKSArICgxICsgIG5lZ19tb29kX2NzX2xhZ19yZWN8c3ViamVjdGNvZGUpLCANCiAgICAgICAgICAgICAgICAgICBkYXRhPWRmX21lZGFsX2NsZWFuX2NvbnRyb2wsDQogICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gR2FtbWEobGluaz1pZGVudGl0eSksIA0KICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBnbG1lckNvbnRyb2woY2FsYy5kZXJpdnMgPSBGLCBvcHRpbWl6ZXI9J2JvYnlxYScsIG9wdEN0cmw9bGlzdChtYXhmdW49MWU2KSkpDQoNCm0yX25lZ19yZWNfcmVtaXR0ZWQgPC0gZ2xtZXIobmVnX21vb2RfY3MgfiByZWNfbWVtX25lZ19tb29kX2NzX2xhZypuZWdfbW9vZF9jc19sYWdfcmVjICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSAgKyByZWNfbWVtX25lZ19tb29kX2NzX2xhZyB8IHN1YmplY3Rjb2RlKSArICgxICsgIG5lZ19tb29kX2NzX2xhZ19yZWN8c3ViamVjdGNvZGUpLCANCiAgICAgICAgICAgICAgICAgICBkYXRhPWRmX21lZGFsX2NsZWFuX3JlbWl0dGVkLA0KICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IEdhbW1hKGxpbms9aWRlbnRpdHkpLCANCiAgICAgICAgICAgICAgICAgICBjb250cm9sID0gZ2xtZXJDb250cm9sKGNhbGMuZGVyaXZzID0gRiwgb3B0aW1pemVyPSdib2J5cWEnLCBvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNikpKQ0KDQptMl9uZWdfcmVjX2RlcHJlc3NlZCA8LSAgZ2xtZXIobmVnX21vb2RfY3MgfiByZWNfbWVtX25lZ19tb29kX2NzX2xhZypuZWdfbW9vZF9jc19sYWdfcmVjICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSAgKyByZWNfbWVtX25lZ19tb29kX2NzX2xhZyB8IHN1YmplY3Rjb2RlKSArICgxICsgIG5lZ19tb29kX2NzX2xhZ19yZWN8c3ViamVjdGNvZGUpLCAgDQogICAgICAgICAgICAgICAgICAgZGF0YT1kZl9tZWRhbF9jbGVhbl9kZXByZXNzZWQsDQogICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gR2FtbWEobGluaz1pZGVudGl0eSksIA0KICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBnbG1lckNvbnRyb2woY2FsYy5kZXJpdnMgPSBGLCBvcHRpbWl6ZXI9J2JvYnlxYScsIG9wdEN0cmw9bGlzdChtYXhmdW49MWU2KSkpDQoNCmFzaXNfb3V0cHV0KHRhYl9tb2RlbChtMl9uZWdfcmVjX2NvbnRyb2wsIG0yX25lZ19yZWNfcmVtaXR0ZWQsIG0yX25lZ19yZWNfZGVwcmVzc2VkLCBzaG93LnNlID0gVCwgc2hvdy5haWMgPSBULCB0cmFuc2Zvcm0gPSBOVUxMLCBkdi5sYWJlbHMgPSBjKCdjb250cm9sJywgJ3JlbWl0dGVkJywgJ2RlcHJlc3NlZCcpKSRrbml0cikgDQpgYGANCg0KDQoNCg0KIyMjIFJlbW90ZSB7LX0NCmBgYHtyfQ0KaDJfbmVnX3JlbW90ZV9lcSA9ICJuZWdfbW9vZF9jcyB+IGNvbmRpdGlvbipyZW1fbWVtX25lZ19tb29kX2NzX2xhZypuZWdfbW9vZF9jc19sYWdfcmVtICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgKDEgKyByZW1fbWVtX25lZ19tb29kX2NzX2xhZyArIG5lZ19tb29kX2NzX2xhZ19yZW18c3ViamVjdGNvZGUpIg0KDQojIHNldCBjbHVzdGVycw0KY2wgPSBtYWtlQ2x1c3RlcihuY29yZXMpDQpyZWdpc3RlckRvUGFyYWxsZWwoY2wpDQoNCiMgcnVuIHBhcmFsbGVsDQpoMl9uZWdfcmVtb3RlX21vZGVscyA9IGZvcmVhY2goZmFtaWx5ID0gbW9kZWxfZmFtaWxpZXMsIC5jb21iaW5lID0gJ2MnLCAucGFja2FnZXMgPSBjKCdsbWVyVGVzdCcpLCAgLmVycm9yaGFuZGxpbmcgPSAicmVtb3ZlIikgJWRvcGFyJSB7DQogIGZpdF9hbGxfbW9kcyhoMl9uZWdfcmVtb3RlX2VxLCBkZl9tZWRhbF9jbGVhbiwgZmFtaWx5KSB9DQpzdG9wQ2x1c3RlcihjbCkNCg0KIyBwcmludCB0aGUgbW9kZWxzIGludG8gYSBzaW5nbGUgdGFibGUNCmFzaXNfb3V0cHV0KCB0YWJfbW9kZWwoaDJfbmVnX3JlbW90ZV9tb2RlbHMsIGR2LmxhYmVscyA9IG5hbWVzKGgyX25lZ19yZW1vdGVfbW9kZWxzKSwgDQogICAgICAgICAgICAgICAgICAgICAgIHNob3cuaWNjID0gVCwgc2hvdy5haWMgPSBULCB0cmFuc2Zvcm0gPSBOVUxMLCBzaG93LnNlID0gVCwgZGlnaXRzID0gMykka25pdHIpDQoNCmBgYA0KDQpDaGVjayBGaW5hbCBNb2RlbA0KYGBge3J9DQpzdW1tYXJ5KGgyX25lZ19yZW1vdGVfbW9kZWxzW1s0XV0pDQpwbG90X2RpYWdub3N0aWNzKGgyX25lZ19yZW1vdGVfbW9kZWxzKQ0KY2FyOjp2aWYoaDJfbmVnX3JlbW90ZV9tb2RlbHNbWzRdXSkNCmBgYA0KDQoNCg0KDQojIyMjIEZvbGxvdy11cCB7LX0NCmBgYHtyfQ0KDQptMl9uZWdfcmVtX2NvbnRyb2wgPC0gZ2xtZXIobmVnX21vb2RfY3MgfiByZW1fbWVtX25lZ19tb29kX2NzX2xhZypuZWdfbW9vZF9jc19sYWdfcmVtICArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgKDEgICsgIHJlbV9tZW1fbmVnX21vb2RfY3NfbGFnfHN1YmplY3Rjb2RlKSArICgxICsgbmVnX21vb2RfY3NfbGFnX3JlbXxzdWJqZWN0Y29kZSksIA0KICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fcmVtb3RlX2NvbnRyb2wsDQogICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gR2FtbWEobGluaz1pZGVudGl0eSksIA0KICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBnbG1lckNvbnRyb2woY2FsYy5kZXJpdnMgPSBGLCBvcHRpbWl6ZXI9J2JvYnlxYScsIG9wdEN0cmw9bGlzdChtYXhmdW49MWU2KSkpDQoNCm0yX25lZ19yZW1fcmVtaXR0ZWQgPC0gZ2xtZXIobmVnX21vb2RfY3MgfiByZW1fbWVtX25lZ19tb29kX2NzX2xhZypuZWdfbW9vZF9jc19sYWdfcmVtICArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgKDEgICsgIHJlbV9tZW1fbmVnX21vb2RfY3NfbGFnfHN1YmplY3Rjb2RlKSArICgxICsgbmVnX21vb2RfY3NfbGFnX3JlbXxzdWJqZWN0Y29kZSksDQogICAgICAgICAgICAgICAgICAgZGF0YT1kZl9tZWRhbF9jbGVhbl9yZW1vdGVfcmVtaXR0ZWQsDQogICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gR2FtbWEobGluaz1pZGVudGl0eSksIA0KICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBnbG1lckNvbnRyb2woY2FsYy5kZXJpdnMgPSBGLCBvcHRpbWl6ZXI9J2JvYnlxYScsIG9wdEN0cmw9bGlzdChtYXhmdW49MWU2KSkpDQoNCm0yX25lZ19yZW1fZGVwcmVzc2VkIDwtICBnbG1lcihuZWdfbW9vZF9jcyB+IHJlbV9tZW1fbmVnX21vb2RfY3NfbGFnKm5lZ19tb29kX2NzX2xhZ19yZW0gICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKyAoMSAgKyAgcmVtX21lbV9uZWdfbW9vZF9jc19sYWd8c3ViamVjdGNvZGUpICsgKDEgKyBuZWdfbW9vZF9jc19sYWdfcmVtfHN1YmplY3Rjb2RlKSwgDQogICAgICAgICAgICAgICAgICAgZGF0YT1kZl9tZWRhbF9jbGVhbl9yZW1vdGVfZGVwcmVzc2VkLA0KICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IEdhbW1hKGxpbms9aWRlbnRpdHkpLCANCiAgICAgICAgICAgICAgICAgICBjb250cm9sID0gZ2xtZXJDb250cm9sKGNhbGMuZGVyaXZzID0gRiwgb3B0aW1pemVyPSdib2J5cWEnLCBvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNikpKQ0KDQphc2lzX291dHB1dCh0YWJfbW9kZWwobTJfbmVnX3JlbV9jb250cm9sLCBtMl9uZWdfcmVtX3JlbWl0dGVkLCBtMl9uZWdfcmVtX2RlcHJlc3NlZCwgc2hvdy5zZSA9IFQsIHNob3cuYWljID0gVCwgdHJhbnNmb3JtID0gTlVMTCwgZHYubGFiZWxzID0gYygnY29udHJvbCcsICdyZW1pdHRlZCcsICdkZXByZXNzZWQnKSkka25pdHIpIA0KYGBgDQoNCg0KIyBFeHBsb3JhdG9yeSBBbmFseXNlcw0KDQojIyBNZWRpYXRpb24gTW9kZWxzIHsudGFic2V0fQ0KDQpGb2xsb3dpbmcgdGhlIHRlc3RzIHdlIHJhbiBmb3IgaHlwb3RoZXNpcyAxLCB3ZSB3b3VsZCBhbHNvIGxpa2UgdG8gc2VlIHdoZXRoZXIgb3Igbm90IG1lZGlhdGlvbiBlZmZlY3RzIGV4aXN0LiANCg0KIyMjIFJlY1BBIHstfQ0KDQpgYGB7cn0NCg0KI2NyZWF0ZSBhIG5ldyBkYXRhZnJhbWUgZm9yIHRoZSByZW1vdGUgdmFyaWFibGVzLCB3aGVyZSB0aGUgcGFydGljaXBhbnRzIHdpdGggdGhlIHNpbmd1bGFyIGRhdGFwb2ludHMgYXJlIHJlbW92ZWQgDQpkZl9tZWRhbF9tb2RlcmF0aW9uID0gIGRmX21lZGFsX2NsZWFuICU+JSANCiAgZmlsdGVyICghKHN1YmplY3Rjb2RlID09IDgyMiB8IHN1YmplY3Rjb2RlID09IDkwNiB8IHN1YmplY3Rjb2RlID09IDcxNykpICU+JSANCiAgZmlsdGVyKCEoaXMubmEocG9zX21vb2QpIHwgaXMubmEocmVjX21lbV9wb3NfbW9vZF9sYWcpKSkgDQoNCiMgbWVkIG1vZGVsDQptZWRfZml0X2gxX3Bvc19yZWMgPC0gbG1lNDo6bG1lcihyZWNfbWVtX3Bvc19tb29kX2xhZyB+IGNvbmRpdGlvbl9kdW1teSArDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFnZSArIGdlbmRlciArIGVkdWNhdGlvbiArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSB8c3ViamVjdGNvZGUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX21lZGFsX21vZGVyYXRpb24pDQojIGZ1bGwgbW9kZWwNCm91dF9maXRfaDFfcG9zX3JlYyA8LWxtZTQ6OmxtZXIocG9zX21vb2QgfiBjb25kaXRpb25fZHVtbXkgKyByZWNfbWVtX3Bvc19tb29kX2xhZyArDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdlICsgZ2VuZGVyICtlZHVjYXRpb24gKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgxICsgcmVjX21lbV9wb3NfbW9vZF9sYWcgfHN1YmplY3Rjb2RlKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl9tZWRhbF9tb2RlcmF0aW9uKQ0KDQojbWVkaWF0aW9uIGFuYWx5c2lzIGZvciBjb250cm9sIGFuZCBkZXByZXNzZWQNCm1lZF9wb3NfcmVjX2RlcCA8LSBtZWRpYXRpb246Om1lZGlhdGUobWVkX2ZpdF9oMV9wb3NfcmVjLCBvdXRfZml0X2gxX3Bvc19yZWMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyZWF0ID0gJ2NvbmRpdGlvbl9kdW1teScgLCBjb250cm9sLnZhbHVlID0gMSwgdHJlYXQudmFsdWUgPSAzICwgIG1lZGlhdG9yID0gJ3JlY19tZW1fcG9zX21vb2RfbGFnJywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXM9MTAwMDApDQpzdW1tYXJ5KG1lZF9wb3NfcmVjX2RlcCkNCg0KYGBgDQoNCg0KIyMjIFJlbU5BIHstfQ0KYGBge3J9DQpkZl9tZWRhbF9tb2RlcmF0aW9uID0gZGZfbWVkYWxfY2xlYW5fcmVtb3RlICU+JSBmaWx0ZXIoIShpcy5uYShuZWdfbW9vZCkgfCBpcy5uYShyZWNfbWVtX25lZ19tb29kX2xhZykpKSANCg0KIyBtZWQgbW9kZWwNCm1lZF9maXRfaDFfbmVnX3JlYyA8LSBsbWU0OjpsbWVyKHJlY19tZW1fbmVnX21vb2RfbGFnIH4gY29uZGl0aW9uX2R1bW15ICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdlICsgZ2VuZGVyICsgZWR1Y2F0aW9uICsgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSB8c3ViamVjdGNvZGUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl9tZWRhbF9tb2RlcmF0aW9uKQ0KIyBmdWxsIG1vZGVsDQpvdXRfZml0X2gxX25lZ19yZWMgPC0gbG1lNDo6bG1lcihuZWdfbW9vZCB+IGNvbmRpdGlvbl9kdW1teSArIHJlY19tZW1fbmVnX21vb2RfbGFnICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZ2UgKyBnZW5kZXIgK2VkdWNhdGlvbiArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgxICsgcmVjX21lbV9uZWdfbW9vZF9sYWd8c3ViamVjdGNvZGUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX21lZGFsX21vZGVyYXRpb24pDQoNCg0KI21lZGlhdGlvbiBhbmFseXNpcyBmb3IgY29udHJvbCBhbmQgcmVtaXR0ZWQNCnN1bW1hcnkobWVkaWF0aW9uOjptZWRpYXRlKG1lZF9maXRfaDFfbmVnX3JlYywgb3V0X2ZpdF9oMV9uZWdfcmVjLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyZWF0ID0gJ2NvbmRpdGlvbl9kdW1teScgLCBtZWRpYXRvciA9ICdyZWNfbWVtX25lZ19tb29kX2xhZycsIGNvbnRyb2wudmFsdWUgPSAxLCB0cmVhdC52YWx1ZSA9IDIgLCAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltcz0xMDAwMCkpDQoNCiNtZWRpYXRpb24gYW5hbHlzaXMgZm9yIGNvbnRyb2wgYW5kIGRlcHJlc3NlZA0Kc3VtbWFyeShtZWRpYXRpb246Om1lZGlhdGUobWVkX2ZpdF9oMV9uZWdfcmVjLCBvdXRfZml0X2gxX25lZ19yZWMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJlYXQgPSAnY29uZGl0aW9uX2R1bW15JyAsICBtZWRpYXRvciA9ICdyZWNfbWVtX25lZ19tb29kX2xhZycsIGNvbnRyb2wudmFsdWUgPSAxLCB0cmVhdC52YWx1ZSA9IDMgLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltcz0xMDAwMCkpDQoNCmBgYA0KDQojIyBNb2RlcmF0ZWQgTWVkaWF0aW9uIHsudGFic2V0fQ0KDQojIyMgUmVtUEEtQ3VyclBBIHstfQ0KYGBge3J9DQoNCmRmX21lZGFsX21vZGVyYXRpb24gPSBkZl9tZWRhbF9jbGVhbl9yZW1vdGUgJT4lIA0KICBmaWx0ZXIoIShpcy5uYShwb3NfbW9vZCkgfCBpcy5uYShyZW1fbWVtX3Bvc19tb29kX2xhZykpKSANCg0KI21lZGlhdGlvbiBmaXJzdA0KbWVkX2ZpdF9oMl9wb3NfcmVtIDwtIGxtZTQ6OmxtZXIocmVtX21lbV9wb3NfbW9vZF9sYWcgfiBjb25kaXRpb25fZHVtbXkgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdlICsgZ2VuZGVyICsgZWR1Y2F0aW9uICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgxIHxzdWJqZWN0Y29kZSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9ZGZfbWVkYWxfbW9kZXJhdGlvbikNCiMgZnVsbCBtb2RlbA0Kb3V0X2ZpdF9oMl9wb3NfcmVtIDwtbG1lNDo6bG1lcihwb3NfbW9vZCB+IGNvbmRpdGlvbl9kdW1teSArIHJlbV9tZW1fcG9zX21vb2RfbGFnIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICArIGFnZSArIGdlbmRlciArZWR1Y2F0aW9uICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSArIHJlbV9tZW1fcG9zX21vb2RfbGFnIHxzdWJqZWN0Y29kZSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfbW9kZXJhdGlvbikNCg0KDQojbWVkaWF0aW9uIGFuYWx5c2lzIGZvciBjb250cm9sIGFuZCByZW1pdHRlZA0KbWVkX3Bvc19yZW1fcmVtIDwtIG1lZGlhdGlvbjo6bWVkaWF0ZShtZWRfZml0X2gyX3Bvc19yZW0sIG91dF9maXRfaDJfcG9zX3JlbSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyZWF0ID0gJ2NvbmRpdGlvbl9kdW1teScgLCBjb250cm9sLnZhbHVlID0gMSwgdHJlYXQudmFsdWUgPSAyICwgIG1lZGlhdG9yID0gJ3JlbV9tZW1fcG9zX21vb2RfbGFnJykNCnN1bW1hcnkobWVkX3Bvc19yZW1fcmVtKQ0KDQojY3JlYXRlIG5ldyBkYXRhZnJhbWVzIHdpdGggb25seSBjb250cm9sIHJlbWl0dGVkIGFuZCBvbmx5IGNvbnRyb2wgZGVwcmVzc2VkDQpkZl9tZWRhbF9jb25fcmVtID0gZGZfbWVkYWxfY2xlYW4gJT4lIGZpbHRlcihjb25kaXRpb249PSdjb250cm9sJyB8IGNvbmRpdGlvbiA9PSAncmVtaXR0ZWQnKQ0KZGZfbWVkYWxfY29uX2RlcCA9IGRmX21lZGFsX2NsZWFuICU+JSBmaWx0ZXIoY29uZGl0aW9uPT0nY29udHJvbCcgfCBjb25kaXRpb24gPT0gJ2RlcHJlc3NlZCcpDQoNCiNyZW1pdHRlZCBncm91cA0KZGZfbWVkYWxfY29uX3JlbSRjb25kaXRpb25fZHVtbXkgPSBidWlsZF9jb250cmFzdChkZl9tZWRhbF9jb25fcmVtJGNvbmRpdGlvbiwgJ2NvbnRyb2wnLCAncmVtaXR0ZWQnKQ0KbWVkX2gyX3Bvc19yZW1fcmVtIDwtIG1kdF9tb2RlcmF0ZWQoZGF0YSA9IGRmX21lZGFsX2Nvbl9yZW0sIElWID1jb25kaXRpb25fZHVtbXksIERWID0gcG9zX21vb2QsIE0gPSByZW1fbWVtX3Bvc19tb29kX2xhZywgTW9kID0gcG9zX21vb2RfbGFnX3JlbSkgDQpyYmluZGxpc3QobWVkX2gyX3Bvc19yZW1fcmVtJHBhdGhzLCBpZGNvbCA9IFQpDQoNCmBgYA0KDQojIyMgUmVtTkEgLSBDdXJyTkEgey19DQpgYGB7ciBwYWdlZC5wcmludD1UUlVFfQ0KZGZfbWVkYWxfbW9kZXJhdGlvbiA9IGRmX21lZGFsX2NsZWFuX3JlbW90ZSAlPiUgZmlsdGVyKCEoaXMubmEobmVnX21vb2QpIHwgaXMubmEocmVtX21lbV9uZWdfbW9vZF9sYWcpKSkgDQoNCiNtZWRpYXRpb24gZmlyc3QNCm1lZF9maXRfaDJfbmVnX3JlbSA8LSBsbWU0OjpsbWVyKHJlbV9tZW1fbmVnX21vb2RfbGFnIH4gY29uZGl0aW9uX2R1bW15ICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdlICsgZ2VuZGVyICsgZWR1Y2F0aW9uICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDEgfHN1YmplY3Rjb2RlKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChjYWxjLmRlcml2cyA9IEYsIG9wdGltaXplcj0nYm9ieXFhJywgb3B0Q3RybD1saXN0KG1heGZ1bj0xZTYpKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPWRmX21lZGFsX21vZGVyYXRpb24pDQoNCm91dF9maXRfaDJfbmVnX3JlbSA8LWxtZTQ6OmxtZXIobmVnX21vb2QgfiBjb25kaXRpb25fZHVtbXkgKyByZW1fbWVtX25lZ19tb29kX2xhZyArDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdlICsgZ2VuZGVyICsgZWR1Y2F0aW9uICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSArIHJlbV9tZW1fbmVnX21vb2RfbGFnIHxzdWJqZWN0Y29kZSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2woY2FsYy5kZXJpdnMgPSBGLCBvcHRpbWl6ZXI9J2JvYnlxYScsIG9wdEN0cmw9bGlzdChtYXhmdW49MWU2KSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfbW9kZXJhdGlvbikNCg0KI21lZGlhdGlvbiBhbmFseXNpcyBmb3IgY29udHJvbCBhbmQgZGVwcmVzc2VkDQptZWRfbmVnX3JlbV9kZXAgPC0gbWVkaWF0aW9uOjptZWRpYXRlKG1lZF9maXRfaDJfbmVnX3JlbSwgb3V0X2ZpdF9oMl9uZWdfcmVtLCAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhdG9yID0gJ3JlbV9tZW1fbmVnX21vb2RfbGFnJywgIHRyZWF0ID0gJ2NvbmRpdGlvbl9kdW1teScgLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbC52YWx1ZSA9IDEsIHRyZWF0LnZhbHVlID0gMyAsIHNpbXM9MTAwMDApIA0Kc3VtbWFyeShtZWRfbmVnX3JlbV9kZXApDQoNCiNtZWRpYXRpb24gYW5hbHlzaXMgZm9yIGNvbnRyb2wgYW5kIHJlbWl0dGVkDQptZWRfbmVnX3JlbV9yZW0gPC0gbWVkaWF0aW9uOjptZWRpYXRlKG1lZF9maXRfaDJfbmVnX3JlbSwgb3V0X2ZpdF9oMl9uZWdfcmVtLCB0cmVhdCA9ICdjb25kaXRpb25fZHVtbXknICwgY29udHJvbC52YWx1ZSA9IDEsIHRyZWF0LnZhbHVlID0gMiAsICBtZWRpYXRvciA9ICdyZW1fbWVtX25lZ19tb29kX2xhZycsIHNpbXM9MTAwMDApIA0Kc3VtbWFyeShtZWRfbmVnX3JlbV9yZW0pDQoNCiNjcmVhdGUgbmV3IGRhdGFmcmFtZXMgd2l0aCBvbmx5IGNvbnRyb2wgcmVtaXR0ZWQgYW5kIG9ubHkgY29udHJvbCBkZXByZXNzZWQNCmRmX21lZGFsX2Nvbl9yZW0gPSBkZl9tZWRhbF9jbGVhbiAlPiUgZmlsdGVyKGNvbmRpdGlvbj09J2NvbnRyb2wnIHwgY29uZGl0aW9uID09ICdyZW1pdHRlZCcpDQpkZl9tZWRhbF9jb25fZGVwID0gZGZfbWVkYWxfY2xlYW4gJT4lIGZpbHRlcihjb25kaXRpb249PSdjb250cm9sJyB8IGNvbmRpdGlvbiA9PSAnZGVwcmVzc2VkJykNCg0KI3JlbWl0dGVkIGdyb3VwDQpkZl9tZWRhbF9jb25fcmVtJGNvbmRpdGlvbl9kdW1teSA9IGJ1aWxkX2NvbnRyYXN0KGRmX21lZGFsX2Nvbl9yZW0kY29uZGl0aW9uLCAnY29udHJvbCcsICdyZW1pdHRlZCcpDQptZWRfaDJfbmVnX3JlbV9yZW0gPC0gbWR0X21vZGVyYXRlZChkYXRhID0gZGZfbWVkYWxfY29uX3JlbSwgSVYgPSBjb25kaXRpb25fZHVtbXksIERWID0gbmVnX21vb2QsIE0gPSByZW1fbWVtX25lZ19tb29kX2xhZywgTW9kID0gbmVnX21vb2RfbGFnX3JlbSkgDQpyYmluZGxpc3QobWVkX2gyX25lZ19yZW1fcmVtJHBhdGhzLCBpZGNvbCA9IFQpDQoNCiNkZXByZXNzZWQgZ3JvdXANCmRmX21lZGFsX2Nvbl9kZXAkY29uZGl0aW9uX2R1bW15ID0gYnVpbGRfY29udHJhc3QoZGZfbWVkYWxfY29uX2RlcCRjb25kaXRpb24sICdjb250cm9sJywgJ2RlcHJlc3NlZCcpDQptZWRfaDJfbmVnX3JlbV9kZXAgPC0gbWR0X21vZGVyYXRlZChkYXRhID0gZGZfbWVkYWxfY29uX2RlcCwgSVYgPSBjb25kaXRpb25fZHVtbXksIERWID0gbmVnX21vb2QsIE0gPSByZW1fbWVtX25lZ19tb29kX2xhZywgTW9kID0gbmVnX21vb2RfbGFnX3JlbSkgDQpyYmluZGxpc3QobWVkX2gyX25lZ19yZW1fZGVwJHBhdGhzLGlkY29sID0gVCkNCiAgDQpgYGANCg0KIyMgQ29udGV4dA0KDQpgYGB7cn0NCmFzaXNfb3V0cHV0KHRhYl9tb2RlbCggKGxtZXIocG9zX21vb2RfY3MgfiByZWNfbWVtX3Bvc19tb29kX2NzX2xhZypjb250ZXh0X2xvY2F0aW9uICsgKDEgIHwgc3ViamVjdGNvZGUpLCBkYXRhID0gZGZfbWVkYWxfY2xlYW4pKSwgDQogICAgICAgICAgIChsbWVyKHBvc19tb29kX2NzIH4gcmVtX21lbV9wb3NfbW9vZF9jc19sYWcqY29udGV4dF9sb2NhdGlvbiArICgxICB8IHN1YmplY3Rjb2RlKSwgZGF0YSA9IGRmX21lZGFsX2NsZWFuKSksDQogICAgICAgICAgICAobG1lcihuZWdfbW9vZF9jcyB+IHJlbV9tZW1fbmVnX21vb2RfY3NfbGFnKmNvbnRleHRfbG9jYXRpb24gKyAoMSAgfCBzdWJqZWN0Y29kZSksIGRhdGEgPSBkZl9tZWRhbF9jbGVhbikpLA0KICAgICAgICAgICAgIChsbWVyKG5lZ19tb29kX2NzIH4gcmVtX21lbV9uZWdfbW9vZF9jc19sYWcqY29udGV4dF9sb2NhdGlvbiArICgxICB8IHN1YmplY3Rjb2RlKSwgZGF0YSA9IGRmX21lZGFsX2NsZWFuKSkpJGtuaXRyKQ0KDQpgYGANCg0KIyMgU1JFVA0KDQpJbiBhZGRpdGlvbiB0byB0aGUgRU1BLCBwYXJ0aWNpcGFudHMgYWxzbyBjb21wbGV0ZWQgdGhlIFNSRVQuIFRoaXMgaXMgYSBsYWIgYmFzZWQgbWVtb3J5IGJpYXMgbWVhc3VyZS4gV2Ugd2FudCB0byBjaGVjayB3aGV0aGVyIG91ciBtZW1vcnkgYmlhcyBtZWFzdXJlcyBmcm9tIHJlYWwtbGlmZSBhcmUgbGlua2VkIHRvIG9uZXMgZnJvbSB0aGUgbGFiIGluIHRoaXMgc3VwcGxlbWVudGFyeSBhbmFseXNpcy4gDQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KCdoYXZlbicpDQpzcmV0X2ZpbGUgPSBmaWxlLnBhdGgoIlo6LyIsICJpbmJveCIsICJ0cmFuc2Zlci0yMDIzLTEyLTA3LTAyLTE1LXBtIiwgJ01FREFMX3ByZSBhbmQgcG9zdCBxdWVzdCBhbmQgcmVtb3RlIHJlY2FsbF93b3JrZmlsZSEhX2ZvciBwYXBlciBvbmx5IHZhci5zYXYnKQ0Kc3JldF9kYXRhID0gcmVhZF9zYXYoc3JldF9maWxlKSANCnNyZXRfZGF0YSA9IHNyZXRfZGF0YSAlPiUgc2VsZWN0KGMoMSw0KSkgJT4lIGRpc3RpbmN0KCkNCg0KZGZfbWVkYWxfcmVjX2NvcjEgPSBkZl9tZWRhbF9jbGVhbiAlPiUNCiAgZHBseXI6OnNlbGVjdChzdWJqZWN0Y29kZSwgcG9zX21vb2QsIHJlY19tZW1fcG9zX21vb2RfbGFnKSAlPiUNCiAgbmEub21pdCgpICU+JSANCiAgZHBseXI6Omdyb3VwX2J5KHN1YmplY3Rjb2RlKSAlPiUNCiAgZHBseXI6Om11dGF0ZShjb3JyID0gIHRyeUNhdGNoKGNvcihyZWNfbWVtX3Bvc19tb29kX2xhZywgcG9zX21vb2QpLCB3YXJuaW5nID0gZnVuY3Rpb24oZSkgTkEpLA0KICAgICAgICAgICAgICAgIG1vZGVsX3R5cGUgPSAiUEFfUkVDIikgJT4lIA0KICBkcGx5cjo6c2VsZWN0KHN1YmplY3Rjb2RlLCBjb3JyLCBtb2RlbF90eXBlKSAlPiUgDQogIGRwbHlyOjpkaXN0aW5jdCgpICAlPiUgdW5ncm91cCgpDQoNCg0KZGZfbWVkYWxfcmVjX2NvcjIgPSBkZl9tZWRhbF9jbGVhbiAlPiUNCiAgZHBseXI6OnNlbGVjdChzdWJqZWN0Y29kZSwgbmVnX21vb2QsIHJlY19tZW1fbmVnX21vb2RfbGFnKSAlPiUNCiAgbmEub21pdCgpICU+JSANCiAgZHBseXI6Omdyb3VwX2J5KHN1YmplY3Rjb2RlKSAlPiUNCiAgZHBseXI6Om11dGF0ZShjb3JyID0gIHRyeUNhdGNoKGNvcihyZWNfbWVtX25lZ19tb29kX2xhZywgbmVnX21vb2QpLCB3YXJuaW5nID0gZnVuY3Rpb24oZSkgTkEpLA0KICAgICAgICAgICAgICAgIG1vZGVsX3R5cGUgPSAiTkFfUkVDIikgJT4lIA0KICBkcGx5cjo6c2VsZWN0KHN1YmplY3Rjb2RlLCBjb3JyLCBtb2RlbF90eXBlKSAlPiUgDQogIGRwbHlyOjpkaXN0aW5jdCgpICU+JSB1bmdyb3VwKCkNCg0KDQpkZl9tZWRhbF9yZW1fY29yMSA9IGRmX21lZGFsX2NsZWFuICU+JQ0KICBkcGx5cjo6c2VsZWN0KHN1YmplY3Rjb2RlLCBwb3NfbW9vZCwgcmVtX21lbV9wb3NfbW9vZF9sYWcpICU+JQ0KICBuYS5vbWl0KCkgJT4lIA0KICBkcGx5cjo6Z3JvdXBfYnkoc3ViamVjdGNvZGUpICU+JQ0KICBkcGx5cjo6bXV0YXRlKGNvcnIgPSB0cnlDYXRjaChjb3IocmVtX21lbV9wb3NfbW9vZF9sYWcsIHBvc19tb29kKSwgd2FybmluZyA9IGZ1bmN0aW9uKGUpIE5BKSwNCiAgICAgICAgICAgICAgICBtb2RlbF90eXBlID0gIlBBX1JFTSIpICU+JSANCiAgZHBseXI6OnNlbGVjdChzdWJqZWN0Y29kZSwgY29yciwgbW9kZWxfdHlwZSkgJT4lIA0KICBkcGx5cjo6ZGlzdGluY3QoKQ0KDQpkZl9tZWRhbF9yZW1fY29yMiA9IGRmX21lZGFsX2NsZWFuICU+JQ0KICBkcGx5cjo6c2VsZWN0KHN1YmplY3Rjb2RlLCBuZWdfbW9vZCwgcmVtX21lbV9uZWdfbW9vZF9sYWcpICU+JQ0KICBuYS5vbWl0KCkgJT4lIA0KICBkcGx5cjo6Z3JvdXBfYnkoc3ViamVjdGNvZGUpICU+JQ0KICBkcGx5cjo6bXV0YXRlKGNvcnIgPSB0cnlDYXRjaChjb3IocmVtX21lbV9uZWdfbW9vZF9sYWcsIG5lZ19tb29kKSwgd2FybmluZyA9IGZ1bmN0aW9uKGUpIE5BKSwNCiAgICAgICAgICAgICAgICBtb2RlbF90eXBlID0gIk5BX1JFTSIpICU+JSANCiAgZHBseXI6OnNlbGVjdChzdWJqZWN0Y29kZSwgY29yciwgbW9kZWxfdHlwZSkgJT4lIA0KICBkcGx5cjo6ZGlzdGluY3QoKQ0KDQoNCmRmX2NvcnMgPSByYmluZGxpc3QobGlzdChkZl9tZWRhbF9yZWNfY29yMSwgZGZfbWVkYWxfcmVjX2NvcjIsIGRmX21lZGFsX3JlbV9jb3IxLCBkZl9tZWRhbF9yZW1fY29yMikpDQoNCmRmX3JlZiA9IG1lcmdlKHNyZXRfZGF0YSwgZGZfY29ycywgYnkueCA9ICdzdWJqZWN0JywgYnkueSA9ICdzdWJqZWN0Y29kZScpDQpkZl9yZWYgPSBkZl9yZWYgJT4lIHJlbmFtZShTUkVUID0gU1JFVF9CaWFzR290bGliX25lZykgJT4lIGRwbHlyOjptdXRhdGUoZ3JvdXAgPSBpZmVsc2Uoc3ViamVjdDw4MDAsICJyZW1pdHRlZCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2Uoc3ViamVjdD49OTAwLCAiY29udHJvbCIsICdkZXByZXNzZWQnKSkgKQ0KDQoNCmZvciAobW9kX3R5cGUgaW4gYygiUEFfUkVDIiwgIlBBX1JFTSIsICJOQV9SRUMiLCAiTkFfUkVNIikpew0KICBwcmludChtb2RfdHlwZSkNCiAgcHJpbnQoc3VtbWFyeShsbShTUkVUIH4gY29ycipncm91cCwgZGF0YSA9IGRmX3JlZiAlPiUgZmlsdGVyKG1vZGVsX3R5cGUgPT0gbW9kX3R5cGUpKSkpDQp9DQoNCg0KYGBgDQoNCg0KIyMgUmVsYXRpdmUgQmlhcw0KDQpIZXJlIHdlIHdhbnQgdG8gY2hlY2sgZm9yIHRoZSByZWxhdGl2ZSBOQS9QQSBiaWFzLiBTbyB3ZSBleHRhY3QgdGhlIHJhbmRvbSBlZmZlY3RzIGZyb20gdGhlIG1vZGVscyB0byBnZXQgdGhlIHNsb3BlcyBmb3IgZWFjaCBzdWJqZWN0LCBhbmQgdGhlbiBjb21wYXJlIHRoZSBOQS9QQSBzbG9wZXMuIFRoaXMgdGVsbHMgdXMgaWYgdGhlcmVzIGEgYmlhcyBiZXR3ZWVuIG5lZ2F0aXZlIGFuZCBwb3NpdGl2ZSBtZW1vcnkuDQoNCmBgYHtyfQ0KDQojIEdldCBpbmRpdmlkdWFsIHNsb3Blcw0KcG9zX3JlY19yZWYgPSBhcy5kYXRhLmZyYW1lKHJhbmVmKGgxX3Bvc19yZWNlbnRfbW9kZWxzW1syXV0pKSAlPiUgZmlsdGVyKHRlcm0hPScoSW50ZXJjZXB0KScpICU+JSBzZWxlY3QoYygzOjUpKQ0KcG9zX3JlbV9yZWYgPSBhcy5kYXRhLmZyYW1lKHJhbmVmKGgxX3Bvc19yZW1vdGVfbW9kZWxzW1syXV0pKSAlPiUgZmlsdGVyKHRlcm0hPScoSW50ZXJjZXB0KScpICU+JSBzZWxlY3QoYygzOjUpKQ0KbmVnX3JlY19yZWYgPSBhcy5kYXRhLmZyYW1lKHJhbmVmKGgxX25lZ19yZWNlbnRfbW9kZWxzW1s0XV0pKSAlPiUgZmlsdGVyKHRlcm0hPScoSW50ZXJjZXB0KScpICU+JSBzZWxlY3QoYygzOjUpKQ0KbmVnX3JlbV9yZWYgPSBhcy5kYXRhLmZyYW1lKHJhbmVmKGgxX25lZ19yZW1vdGVfbW9kZWxzW1s0XV0pKSAlPiUgZmlsdGVyKHRlcm0hPScoSW50ZXJjZXB0KScpICU+JSBzZWxlY3QoYygzOjUpKQ0KcG9zX3JlY19yZWYkbW9kID0gIlBBX1JFQyINCnBvc19yZW1fcmVmJG1vZCA9ICJQQV9SRU0iDQpuZWdfcmVjX3JlZiRtb2QgPSAiTkFfUkVDIg0KbmVnX3JlbV9yZWYkbW9kID0gIk5BX1JFTSINCg0KIyBQdXQgdG9nZXRoZXIgaW50byBhIG5ldyBkYXRhIGZyYW1lDQpkZl9yZWYgPSByYmluZGxpc3QobGlzdChwb3NfcmVjX3JlZiwgcG9zX3JlbV9yZWYsIG5lZ19yZWNfcmVmLCBuZWdfcmVtX3JlZikpDQpkZl9yZWYgPSBkZl9yZWYgJT4lIA0KICBkcGx5cjo6bXV0YXRlKHN1YiA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGdycCkpKSAlPiUNCiAgZHBseXI6Om11dGF0ZShncm91cCA9IGlmZWxzZShzdWIgPD0gODAwLCAicmVtaXR0ZWQiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2Uoc3ViPj05MDAsICJjb250cm9sIiwgJ2RlcHJlc3NlZCcpKSApDQoNCmRmX3JlZl9yZWMgPSBkZl9yZWYgJT4lIGZpbHRlcihtb2QgPT0gJ1BBX1JFQycgfCBtb2Q9PSdOQV9SRUMnKQ0KZGZfcmVmX3JlbSA9IGRmX3JlZiAlPiUgZmlsdGVyKG1vZCA9PSAnUEFfUkVNJyB8IG1vZD09J05BX1JFTScpDQpzdW1tYXJ5KGxtZXIoY29uZHNkIH4gbW9kKmdyb3VwICsgKDF8c3ViKSwgZGF0YSA9IGRmX3JlZl9yZWMpKQ0Kc3VtbWFyeShsbWVyKGNvbmRzZCB+IG1vZCpncm91cCArICgxfHN1YiksIGRhdGEgPSBkZl9yZWZfcmVtKSkNCmBgYA0KDQoNCg0KIyBQbG90cw0KDQpGaXJzdCB3ZSBzZXQgb3VyIHRoZW1lIGFuZCBmaXggdGhlIGRhdGEgZm9yIHRoZSBmaWd1cmVzIHdlIHdhbnQNCmBgYHtyfQ0KIyBUaGVtZQ0KZ2d0aGVtZSA9IHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLCANCiAgICAgICAgICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiKSwgDQogICAgICAgICAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJncmV5OTAiKSwNCiAgICAgICAgICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9saW5lKGNvbG9yID0gImdyZXkxMDAiKSwNCiAgICAgICAgICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiZ3JleTgwIiwgZmlsbCA9ICJ0cmFuc3BhcmVudCIpKQ0KDQojIEVzdGltYXRlIHRoZSBTRA0KZGZfbWVkYWxfY2xlYW4yID0gZGZfbWVkYWxfY2xlYW4gJT4lIA0KICBtdXRhdGUocG9zX21vb2Rfc2QgPSBpZmVsc2UoIChwb3NfbW9vZF9jc19sYWdfcmVjID4gKG1lYW4ocG9zX21vb2RfY3NfbGFnX3JlYywgbmEucm09VCkrc2QocG9zX21vb2RfY3NfbGFnX3JlYywgbmEucm09VCkpKSwgIisxU0QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSggKHBvc19tb29kX2NzX2xhZ19yZWMgPCAobWVhbihwb3NfbW9vZF9jc19sYWdfcmVjLCBuYS5ybT1UKS1zZChwb3NfbW9vZF9jc19sYWdfcmVjLCBuYS5ybSA9VCkpKSwgIi0xU0QiLCAiTWVhbiIpKSkgJT4lIA0KICAgIG11dGF0ZShuZWdfbW9vZF9zZCA9IGlmZWxzZSggKG5lZ19tb29kX2NzX2xhZ19yZWMgPiAobWVhbihuZWdfbW9vZF9jc19sYWdfcmVjLCBuYS5ybT1UKStzZChuZWdfbW9vZF9jc19sYWdfcmVjLCBuYS5ybT1UKSkpLCAiKzFTRCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKCAobmVnX21vb2RfY3NfbGFnX3JlYyA8IChtZWFuKG5lZ19tb29kX2NzX2xhZ19yZWMsIG5hLnJtPVQpLXNkKG5lZ19tb29kX2NzX2xhZ19yZWMsIG5hLnJtID1UKSkpLCAiLTFTRCIsICJNZWFuIikpKQ0KDQojIEZpeCBmYWN0b3IgbGV2ZWxzDQpkZl9tZWRhbF9jbGVhbjIkQ29uZGl0aW9uID0gIGZhY3RvcihkZl9tZWRhbF9jbGVhbjIkY29uZGl0aW9uLCBsZXZlbHM9YygnY29udHJvbCcsICdyZW1pdHRlZCcsICdkZXByZXNzZWQnICksIGxhYmVscz1jKCdOZXZlci1EZXByZXNzZWQnLCAnUmVtaXR0ZWQnLCAnRGVwcmVzc2VkJykpDQpkZl9tZWRhbF9jbGVhbjIkcG9zX21vb2Rfc2QgPSAgZmFjdG9yKGRmX21lZGFsX2NsZWFuMiRwb3NfbW9vZF9zZCwgbGV2ZWxzPWMoJy0xU0QnLCAnTWVhbicsICcrMVNEJyApKQ0KZGZfbWVkYWxfY2xlYW4yJG5lZ19tb29kX3NkID0gIGZhY3RvcihkZl9tZWRhbF9jbGVhbjIkbmVnX21vb2Rfc2QsIGxldmVscz1jKCctMVNEJywgJ01lYW4nLCAnKzFTRCcgKSkNCg0KDQpgYGANCg0KIyMjIFBBLUNVUi1SRUMNCmBgYHtyfQ0KDQojIFBsb3QNCnBsb3RfcGFfcmVjID0gZ2dwbG90KGRmX21lZGFsX2NsZWFuMiwgYWVzKHggPSByZWNfbWVtX3Bvc19tb29kX2NfbGFnLCB5PXBvc19tb29kX2MsIGNvbG9yID0gcG9zX21vb2Rfc2QsIGZpbGwgPSBwb3NfbW9vZF9zZCkpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2xtJywgYWxwaGEgPSAwLjE1KSArDQogIGxhYnMoIHggPSBicXVvdGUocGFzdGUoUkVDW1BBXSwgIiAoc3ViamVjdC1jZW50ZXJlZCBhLnUuKSIpKSwgeSA9ICJQQSAoc3ViamVjdC1jZW50ZXJlZCBhLnUuKSIsIGNvbG9yID0gYnF1b3RlKENVUltQQV0pLCBmaWxsID0gYnF1b3RlKENVUltQQV0pICkgKw0KICBnZ3RoZW1lICsgDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSB3ZXNhbmRlcnNvbjo6d2VzX3BhbGV0dGUobj0zLCBuYW1lPSdHcmFuZEJ1ZGFwZXN0MicgKSkgICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gd2VzYW5kZXJzb246Ondlc19wYWxldHRlKG49MywgbmFtZT0nR3JhbmRCdWRhcGVzdDInICkpICArDQogIGZhY2V0X2dyaWQoLn5Db25kaXRpb24pIA0KIA0KcGxvdF9wYV9yZWMNCmBgYA0KDQojIyMgUEEtQ1VSLVJFQw0KDQpgYGB7cn0NCg0KIyBQbG90DQpwbG90X25hX3JlYyA9IA0KICBnZ3Bsb3QoZGZfbWVkYWxfY2xlYW4yLCBhZXMoeCA9IHJlY19tZW1fbmVnX21vb2RfY19sYWcsIHk9bmVnX21vb2RfYywgY29sb3IgPSBuZWdfbW9vZF9zZCwgZmlsbCA9IG5lZ19tb29kX3NkKSkgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nLCBhbHBoYSA9IDAuMTUpICsNCiAgbGFicyggeCA9IGJxdW90ZShwYXN0ZShSRUNbJ05BJ10sICIgKHN1YmplY3QtY2VudGVyZWQgYS51LikiKSksIHkgPSAiTkEgKHN1YmplY3QtY2VudGVyZWQgYS51LikiLCBjb2xvciA9IGJxdW90ZShDVVJbIk5BIl0pLCBmaWxsID0gYnF1b3RlKENVUlsiTkEiXSkgKSArDQogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHdlc2FuZGVyc29uOjp3ZXNfcGFsZXR0ZShuPTMsIG5hbWU9J0dyYW5kQnVkYXBlc3QyJyApKSAgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB3ZXNhbmRlcnNvbjo6d2VzX3BhbGV0dGUobj0zLCBuYW1lPSdHcmFuZEJ1ZGFwZXN0MicgKSkgICsNCiAgZ2d0aGVtZSArIA0KICBmYWNldF9ncmlkKC5+Q29uZGl0aW9uKSANCnBsb3RfbmFfcmVjDQpgYGANCg0KIyMjIENvbWJpbmVkIFBsb3QgZm9yIHB1Yg0KYGBge3J9DQpnZ2FycmFuZ2UoTkEsIHBsb3RfcGFfcmVjLCBOQSwgIHBsb3RfbmFfcmVjLA0KICAgICAgICAgIHdpZHRocz1jKDAuMDUsIDEsIDAuMDUsIDEpLCBuY29sID0gMiwgbnJvdyA9IDIsDQogICAgICAgICAgbGFiZWxzPWMoIkEiLCBOQSwgIkIiKSkNCmdnc2F2ZSgiZmlndXJlcy9maWcxX3RocmVld2F5LnBkZiIsIGRldmljZSA9ICdwZGYnLCBkcGkgPSAzMjAsIGhlaWdodCA9IDYpDQoNCmBgYA0KDQoNCg0KDQoNCg0K